Codeforces Round #755 (Div. 2, based on Technocup 2022 Elimination Round 2) E题

题意是 给你 个长度为 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

猜你喜欢

转载自blog.csdn.net/qqqingyi/article/details/121399239
今日推荐