Codeforces Round #632 (Div. 2) C. Eugene and an array

C. Eugene and an array

题目链接-C. Eugene and an array
在这里插入图片描述
在这里插入图片描述
题目大意
数组内和不为 0 0 的连续子序列被称为好的序列,统计数组 a n an 中有几个好的序列

解题思路
+ 前缀和+计数

  • 求出前缀和,前缀和 p r e [ i ] = p r e [ j ] pre[i]=pre[j] 意味着 a [ i + 1 ] a [ j ] a[i+1]-a[j] 这一段的和为 0 0
  • map维护当前出现过的前缀和的下标,即用map记录 s u m sum 上一次出现的位置,即左端点
  • k k 来记录当前没有前缀和为 0 0 的区间的左端点(左端点最大值),以当前点 i i 为右端点,因为区间为左开右闭,所以 k k 要初始化为 1 1
  • 所以满足条件的区间就是 ( k , i ] (k,i] ,然后区间内数的个数就是增加当前这个点后增加的好序列个数,即不包含子串和为 0 0 的个数为 i ( k + 1 ) i−(k+1) ,累加即可
  • 具体操作见代码

附上代码

#pragma GCC optimize("-Ofast","-funroll-all-loops")
//#pragma GCC diagnostic error "-std=c++11"
#include<bits/stdc++.h>
#define int long long
#define lowbit(x) (x &(-x))
#define endl '\n'
using namespace std;
const int INF=0x3f3f3f3f;
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const double PI=acos(-1.0);
const double e=exp(1.0);
const double eps=1e-10;
const int M=1e9+7;
const int N=1e5+10;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
map<int,int> mp;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	mp[0]=0;//第一个数前面前缀和为0
	int n,ans=0,tmp=0,k=-1;
	cin>>n;
	for(int i=1;i<=n;i++){
		int t;
		cin>>t;
		tmp+=t;//记录前缀和
		if(mp.count(tmp))//判断tmp是否出现过
			//因为初始化mp[0]=0,所以用if(mp[tmp])判断会出错
			k=max(k,mp[tmp]);
		ans+=i-k-1;//注意边界问题
		mp[tmp]=i;
	}
	cout<<ans<<endl;
	return 0;
}

发布了175 篇原创文章 · 获赞 15 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Fiveneves/article/details/105419497