Eugene and an array(尺取法)Codeforces Round #632 (Div. 2)

在這裏插入圖片描述

題目大意

       如果一個數組中不存在某個子數組的和等於00,則認爲此數組爲goodgood。現給出一個長度爲n(1<=n<=2105)n(1<=n<=2·10^5)的數組,問其符合goodgood的子數組個數是多少?

分析過程

       經過分析,不難發現,要解決題目所求首先就是找到和爲00的子數組,這個在求一遍前綴和之後很容易看出,如果說前綴和數組中某兩個位置的值相等(設這兩個位置爲leftleftrightright,即滿足sum[left]==sum[right]sum[left]==sum[right]),那麼區間[left+1,right][left+1,right]這一段的和必然爲00。分析到這一步之後,我們嘗試使用尺取法,定義雙指針left,rightleft,right,從左到右枚舉答案區間的右端點rightright,並且移動leftleft指針,以保證每一時刻雙指針管轄的範圍內不存在和爲00的子數組序列,這個時候,以rightright爲右端點對應的貢獻就是rightleftright-left,我們把它累加到答案中即可。
       具體實現時可以使用一個mapmap來實時更新標記區間中的情況。注意一個細節,要考慮某位置的前綴和爲00的情況,這個時候相當於是和sum[0]sum[0]相等,所以一開始要初始化標記sum[0]sum[0]

AC代碼

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;
typedef long long ll;
ll n, a, sum[maxn];
map<ll, bool> mp;
ll solve(){ //尺取 
	ll ans = 0, left = 0, right = 1; //以right爲答案區間的右端點,從左到右枚舉 
	mp[0] = true;
	while(right <= n){
		while(mp[sum[right]]){
			mp[sum[left]] = false;
			++left;
		}
		ans += right - left;
		mp[sum[right]] = true;
		++right;
	}
	return ans;
}
int main(){
	ll i, j;
	ios::sync_with_stdio(false);
	cin>>n;
	for(i=1;i<=n;++i){
		cin>>a;
		sum[i] = sum[i-1] + a;
	}
	cout<<solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章