题意是 给你 个长度为 n的 数组 找到 子区间 l ~ r 使用1个操作 ai - 1 ai +1 - 1使得 所有子区间元素变为 0 的个数
方法一: 考虑如何让子区间变为0 那肯定是 从左到右不停减去自身 使得最后一个元素 为 0 既 al - al + 1 <= 0 al + 1 - al - al + 2 <= 0 直到最后一个为0即可 我们只需要找到 第一个 > 0的位置并且 找到 0的个数就行 所以我们考虑维护 维护一个B数组上述1 ~ n的前缀 若我们要使 l为第一个位置怎么办呢 当 l为奇数的时候 我们发现 B数组的形式为 -a[l + 1] + a[l] - a[l - 1] + a[l - 2]…+a[1] 我们要将他变为 a[l] - a[l + 1] 所以我们要加上B[l - 2] 若为偶数 我们只需要减去 B[l - 2]所以我们线段树 还要分 奇数偶数来维护 怎么找到 区间个数呢 我们只需要分奇数偶数维护主席树即可
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 3e5 + 10;
typedef long long ll;
int a[N],b[N],c[N * 3],len;
struct tre{
int x,y;
}tree[N * 4];
tre max(tre x,tre y){
tre s;
if(x.x >= y.x) s.x = x.x;
else s.x = y.x;
if(x.y >= y.y) s.y = x.y;
else s.y = y.y;
return s;
}
void build(int s,int t,int p){
if(s == t){
int pos = lower_bound(c + 1,c + len + 1,b[s]) - c;
//cout << pos << "GGG" << endl;
if(s & 1){
tree[p].x = pos;
tree[p].y = 0;
}else tree[p].y = pos,tree[p].x = 0;
return;
}
int mid = s + t >> 1;
build(s,mid,p * 2);
build(mid + 1,t,p * 2 + 1);
tree[p] = max(tree[p * 2],tree[p * 2 + 1]);
return;
}
int query(int s,int t,int p,int l,int r,int x,int y,int type){
//if(l == 1) cout << s<< " " <<t << "DDDDDDDDDDDDDDDDDDDDDDD" << endl;
if(p == 1 && type == 0) swap(x,y);
if(s == t && s >= l && t <= r){
/*if(l == 1)
cout << "GGGGG" << endl;*/
return s;
}
if(s == t) return 0;
int mid = s + t >> 1;
if(l <= mid && (tree[p * 2].x > x || tree[p * 2].y > y)){
int k = query(s,mid,p * 2,l,r,x,y,type);
if(!k && mid < r && (tree[p * 2 + 1].x > x || tree[p * 2 + 1].y > y)) return query(mid + 1,t,p * 2 + 1,l,r,x,y,type);
return k;
}
if(mid < r && (tree[p * 2 + 1].x > x || tree[p * 2 + 1].y > y)) return query(mid + 1,t,p * 2 + 1,l,r,x,y,type);
return 0;
}
struct node{
int jx,ox,l,r;
}tr[N * 25];
int T[N];
int tot;
int build2(int p,int s,int t){
p = ++tot;
tr[p].jx = 0,tr[p].ox = 0;
if(s == t) return p;
int mid = s + t >> 1;
tr[p].l = build2(tr[p].l,s,mid);
tr[p].r = build2(tr[p].r,mid + 1,t);
return p;
}
int update2(int x,int y,int l,int r,int k,int type){
x = ++tot;
if(type == 1) tr[x].jx = tr[y].jx + 1,tr[x].ox = tr[y].ox;
else tr[x].ox = tr[y].ox + 1,tr[x].jx = tr[y].jx;
tr[x].l = tr[y].l,tr[x].r = tr[y].r;
int mid = l + r >> 1;
if(l == r) return x;
if(l <= k && mid >= k) tr[x].l = update2(tr[x].l,tr[y].l,l,mid,k,type);
if(mid < k && k <= r) tr[x].r = update2(tr[x].r,tr[y].r,mid + 1,r,k,type);
return x;
}
int query2(int x,int y,int l,int r,int k,int type){
if(l == r){
if(type == 1){
return tr[x].jx - tr[y].jx;
}
else{
return tr[x].ox - tr[y].ox;
}
}
int mid = l + r >> 1;
if(l <= k && k <= mid) return query2(tr[x].l,tr[y].l,l,mid,k,type);
if(mid < k && k <= r) return query2(tr[x].r,tr[y].r,mid + 1,r,k,type);
return 0;
}
int main(){
int t;
cin >> t;
while(t--){
int n;
cin >> n;
tot = 0;
int cnt = 0;
ll sum = 0;
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
c[++cnt] = a[i];
if(a[i] == 0) sum++;
T[i] = 0;
}
b[0] = -a[1];
c[++cnt] = b[0];
c[++cnt] = -b[0];
for(int j = 1; j < n; j++){
b[j] = -b[j - 1] - a[j + 1];
//cout << b[j] << " ";
c[++cnt] = b[j];
c[++cnt] = -b[j];
}
//cout << endl;
sort(c + 1,c + cnt + 1);
len = unique(c + 1,c + cnt + 1) - c - 1;
build(1,n,1);
T[0] = build2(T[0],1,len);
for(int j = 1; j <= n; j++){
int pos = lower_bound(c + 1,c + len + 1,b[j]) - c;
T[j] = update2(T[j],T[j - 1],1,len,pos,j & 1);
}
int pos = lower_bound(c + 1,c + len + 1,0) - c;
//cout << query2(T[5],T[0],1,len,pos,1) << " " << query2(T[5],T[0],1,len,pos,0) <<" "<< pos << " " << "GGGGGGGGGG" << endl;
for(int i = 1; i <= n - 1; i++){
int x = (i >= 2?b[i - 2]: 0);
int y = (i >= 2?-b[i - 2]: 0);
int pos = lower_bound(c + 1,c + len + 1,x) - c;
int pos2 = lower_bound(c + 1,c + len + 1,-x) - c;
int pos3 = lower_bound(c + 1,c + len + 1,y) - c;
int s = query(1,n,1,i,n,pos,pos3,i & 1);
//cout <<i << " " << s << " " << pos << " " << pos3 << "GGG" << endl;
if(s == 0) s = n;
if(s > n) s = n;
--s;
//cout << s << endl;
if(i & 1){
//cout << sum << " " << x << " " << c[pos] << " " << pos<< endl;
if(c[pos] == x){
sum += query2(T[s],T[i - 1],1,len,pos,1);
}
//if(i == 1) cout << s << " " << i - 1 << " " << sum << "GGGGGGGGGG" << endl;
if(c[pos2] == -x)
sum += query2(T[s],T[i - 1],1,len,pos2,0);
}else{
//if(i == 2) cout << -x << " " << pos2 << " " << endl;
if(c[pos2] == -x)
sum += query2(T[s],T[i - 1],1,len,pos2,1);
if(c[pos] == x)
sum += query2(T[s],T[i - 1],1,len,pos,0);
}
//cout << sum << "asd" << endl;
}
cout << sum << endl;
}
return 0;
}
/*
9
1 5 1 1 2 1 1 7 1
*/
//3