题目
题意:
给你一个序列,这个序列可以删除开始的元素和结尾的元素,删完后如果满足序列中连续的相加没有一个为 则算好的,最后问好的有多少个。
思路:
因为我们求出来的不能出现和为 的数值,所以如果用前缀和来表示的话,那么就是两个前缀和不能是同一数字,如果是的话,那么就说明了中间的和相加是 ,所以这个时候我们能够取的地方就是前一个一样数字的后一个元素,这样才可以保证中间不可能出现相加和为 的情况,然后在我们取前缀和的时候实际上就已经将删除结尾的元素算进去了,比如你取第 个元素,那么 ~ 的元素是不是相当于删除的状态,每一次都加上 ,是因为我们以 点为结束点,那么在 ~ 中,都存在符合条件的,所以以 点为结束点,那么是不是有 ~ 为一种, ~ 等等,所以最后就是 。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
const int maxn = 2e5 + 10;
ll ql[maxn] = {0}, a[maxn], qr[maxn] = {0};
map<ll, int> mp;
int main() {
int n, Max = 0;
read(n);
for (int i = 1; i <= n; i++) read(a[i]), ql[i] = ql[i - 1] + a[i];
mp[0] = 1;
ll ans = 0;
for (int i = 1; i <= n; i++) {
Max = max(Max, mp[ql[i]]);
ans += 1ll * (i - Max);
mp[ql[i]] = i + 1;
}
printf("%lld", ans);
return 0;
}