线段树10pts求调

P2572 [SCOI2010] 序列操作

toolong114514 @ 2023-11-17 20:50:48

#include<algorithm>
#include<iostream>
using namespace std;
const int N=1e6+10;
struct node{
    int l,r;
    int sum1,l1,r1,lgt1,sum0,l0,r0,lgt0;
    int laz1,laz2;
}tree[4*N];
int a[N];
int n,m;
void push_up(int pos){
    //对1 
    tree[pos].sum1=tree[pos*2].sum1+tree[pos*2+1].sum1;
    tree[pos].lgt1=max(max(tree[pos*2].lgt1,tree[pos*2+1].lgt1),tree[pos*2].r1+tree[pos*2+1].l1);
    tree[pos].l1=tree[pos*2].l1;
    if(tree[pos*2].sum1==tree[pos*2].r-tree[pos*2].l+1) tree[pos].l1=tree[pos*2].sum1+tree[pos*2+1].l1;
    tree[pos].r1=tree[pos*2+1].r1;
    if(tree[pos*2+1].sum1==tree[pos*2+1].r-tree[pos*2+1].l+1) tree[pos].r1=tree[pos*2+1].sum1+tree[pos*2].r1;
    //对0 
    tree[pos].sum0=tree[pos*2].sum0+tree[pos*2+1].sum0;
    tree[pos].lgt0=max(max(tree[pos*2].lgt0,tree[pos*2+1].lgt0),tree[pos*2].r0+tree[pos*2+1].l0);
    tree[pos].l0=tree[pos*2].l0;
    if(tree[pos*2].sum0==tree[pos*2].r-tree[pos*2].l+1) tree[pos].l0=tree[pos*2].sum0+tree[pos*2+1].l0;
    tree[pos].r0=tree[pos*2+1].r0;
    if(tree[pos*2+1].sum0==tree[pos*2+1].r-tree[pos*2+1].l+1) tree[pos].r0=tree[pos*2+1].sum0+tree[pos*2].r0;
}
void push_down(int pos){
    if(tree[pos].laz1==1){
        tree[pos*2].sum1=1;
        tree[pos*2].l1=1;
        tree[pos*2].r1=1;
        tree[pos*2].lgt1=1;
        tree[pos*2+1].sum1=1;
        tree[pos*2+1].l1=1;
        tree[pos*2+1].r1=1;
        tree[pos*2+1].lgt1=1;

        tree[pos*2].sum0=0;
        tree[pos*2].l0=0;
        tree[pos*2].r0=0;
        tree[pos*2].lgt0=0;
        tree[pos*2+1].sum0=0;
        tree[pos*2+1].l0=0;
        tree[pos*2+1].r0=0;
        tree[pos*2+1].lgt0=0;

        tree[pos*2].laz1=tree[pos*2+1].laz1=1;
    }
    if(tree[pos].laz1==0){
        tree[pos*2].sum1=0;
        tree[pos*2].l1=0;
        tree[pos*2].r1=0;
        tree[pos*2].lgt1=0;
        tree[pos*2+1].sum1=0;
        tree[pos*2+1].l1=0;
        tree[pos*2+1].r1=0;
        tree[pos*2+1].lgt1=0;

        tree[pos*2].sum0=1;
        tree[pos*2].l0=1;
        tree[pos*2].r0=1;
        tree[pos*2].lgt0=1;
        tree[pos*2+1].sum0=1;
        tree[pos*2+1].l0=1;
        tree[pos*2+1].r0=1;
        tree[pos*2+1].lgt0=1;

        tree[pos*2].laz1=0;
        tree[pos*2+1].laz1=0;
    }
    tree[pos].laz1=-1;
    if(tree[pos].laz2==-1){
        swap(tree[pos*2].l0,tree[pos*2].l1);
        swap(tree[pos*2].r0,tree[pos*2].r1);
        swap(tree[pos*2].lgt0,tree[pos*2].lgt1);
        swap(tree[pos*2].sum0,tree[pos*2].sum1);

        swap(tree[pos*2+1].l0,tree[pos*2+1].l1);
        swap(tree[pos*2+1].r0,tree[pos*2+1].r1);
        swap(tree[pos*2+1].lgt0,tree[pos*2+1].lgt1);
        swap(tree[pos*2+1].sum0,tree[pos*2+1].sum1);

        tree[pos*2].laz2*=-1;
        tree[pos*2+1].laz2*=-1;
    }
    tree[pos].laz2=1;
}
void build(int pos,int lft,int rgt){
    tree[pos].l=lft;
    tree[pos].r=rgt;
    tree[pos].laz1=-1;
    tree[pos].laz2=1; 
    if(lft==rgt){
        if(a[lft]==1){
            tree[pos].sum1=1;
            tree[pos].l1=1;
            tree[pos].r1=1;
            tree[pos].lgt1=1;
        }else{
            tree[pos].sum0=1;
            tree[pos].l0=1;
            tree[pos].r0=1;
            tree[pos].lgt0=1;
        }
        return;
    }
    int mid=(lft+rgt)/2;
    build(pos*2,lft,mid);
    build(pos*2+1,mid+1,rgt);
    push_up(pos);
}
void fill1(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt){
        tree[pos].sum1=tree[pos].r-tree[pos].l+1;
        tree[pos].l1=tree[pos].r-tree[pos].l+1;
        tree[pos].r1=tree[pos].r-tree[pos].l+1;
        tree[pos].lgt1=tree[pos].r-tree[pos].l+1;

        tree[pos].sum0=0;
        tree[pos].l0=0;
        tree[pos].r0=0;
        tree[pos].lgt0=0;

        tree[pos].laz1=1;
        tree[pos].laz2=1;
        return;
    }
    if(tree[pos].r<lft||rgt<tree[pos].l) return;
    push_down(pos);
    fill1(pos*2,lft,rgt);
    fill1(pos*2+1,lft,rgt);
    push_up(pos);
}
void fill0(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt){
        tree[pos].sum0=tree[pos].r-tree[pos].l+1;
        tree[pos].l0=tree[pos].r-tree[pos].l+1;
        tree[pos].r0=tree[pos].r-tree[pos].l+1;
        tree[pos].lgt0=tree[pos].r-tree[pos].l+1;

        tree[pos].sum1=0;
        tree[pos].l1=0;
        tree[pos].r1=0;
        tree[pos].lgt1=0;

        tree[pos].laz1=0;
        tree[pos].laz2=1;
        return;
    }
    if(tree[pos].r<lft||rgt<tree[pos].l) return;
    push_down(pos);
    fill0(pos*2,lft,rgt);
    fill0(pos*2+1,lft,rgt);
    push_up(pos);
}
void rev(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt){
        swap(tree[pos].l0,tree[pos].l1);
        swap(tree[pos].r0,tree[pos].r1);
        swap(tree[pos].lgt0,tree[pos].lgt1);
        swap(tree[pos].sum0,tree[pos].sum1);
        tree[pos].laz2*=-1;
        return;
    }
    if(tree[pos].r<lft||rgt<tree[pos].l) return;
    push_down(pos);
    rev(pos*2,lft,rgt);
    rev(pos*2+1,lft,rgt);
    push_up(pos);
}
int ask1(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt) return tree[pos].sum1;
    if(tree[pos].r<lft||rgt<tree[pos].l) return 0;
    push_down(pos);
    return ask1(pos*2,lft,rgt)+ask1(pos*2+1,lft,rgt);
}
node ask2(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt) return tree[pos];
    push_down(pos);
    if(tree[pos*2].r<lft) return ask2(pos*2+1,lft,rgt);
    if(rgt<tree[pos*2+1].l) return ask2(pos*2,lft,rgt);
    int mid=(tree[pos].l+tree[pos].r)/2;
    node t1=ask2(pos*2,lft,rgt);
    node t2=ask2(pos*2+1,lft,rgt);
    node ans;
    ans.lgt1=max(t1.r1+t2.l1,max(t1.lgt1,t2.lgt1));
    ans.l1=t1.l1;
    ans.r1=t2.r1;
    if(t1.sum1==mid-tree[pos].l+1) ans.l1=t1.sum1+t2.l1;
    if(t2.sum1==tree[pos].r-mid) ans.r1=t2.sum1+t1.r1;
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    build(1,1,n);
    while(m--){
        int op,ll,rr;
        cin>>op>>ll>>rr;
        ll++;
        rr++;
        if(op==0) fill0(1,ll,rr);
        if(op==1) fill1(1,ll,rr);
        if(op==2) rev(1,ll,rr);
        if(op==3) cout<<ask1(1,ll,rr)<<endl;
        if(op==4) cout<<ask2(1,ll,rr).lgt1<<endl;
    }
    return 0;
}

by toolong114514 @ 2023-11-17 20:57:23

现在的代码,修正了一些大的bug。

#include<algorithm>
#include<iostream>
using namespace std;
const int N=1e6+10;
struct node{
    int l,r;
    int sum1,l1,r1,lgt1,sum0,l0,r0,lgt0;
    int laz1,laz2;
}tree[4*N];
int a[N];
int n,m;
void push_up(int pos){
    //对1 
    tree[pos].sum1=tree[pos*2].sum1+tree[pos*2+1].sum1;
    tree[pos].lgt1=max(max(tree[pos*2].lgt1,tree[pos*2+1].lgt1),tree[pos*2].r1+tree[pos*2+1].l1);
    tree[pos].l1=tree[pos*2].l1;
    if(tree[pos*2].sum1==tree[pos*2].r-tree[pos*2].l+1) tree[pos].l1=tree[pos*2].sum1+tree[pos*2+1].l1;
    tree[pos].r1=tree[pos*2+1].r1;
    if(tree[pos*2+1].sum1==tree[pos*2+1].r-tree[pos*2+1].l+1) tree[pos].r1=tree[pos*2+1].sum1+tree[pos*2].r1;
    //对0 
    tree[pos].sum0=tree[pos*2].sum0+tree[pos*2+1].sum0;
    tree[pos].lgt0=max(max(tree[pos*2].lgt0,tree[pos*2+1].lgt0),tree[pos*2].r0+tree[pos*2+1].l0);
    tree[pos].l0=tree[pos*2].l0;
    if(tree[pos*2].sum0==tree[pos*2].r-tree[pos*2].l+1) tree[pos].l0=tree[pos*2].sum0+tree[pos*2+1].l0;
    tree[pos].r0=tree[pos*2+1].r0;
    if(tree[pos*2+1].sum0==tree[pos*2+1].r-tree[pos*2+1].l+1) tree[pos].r0=tree[pos*2+1].sum0+tree[pos*2].r0;
}
void push_down(int pos){
    if(tree[pos].laz1==1){
        tree[pos*2].sum1=tree[pos*2].r-tree[pos*2].l+1;
        tree[pos*2].l1=tree[pos*2].r-tree[pos*2].l+1;
        tree[pos*2].r1=tree[pos*2].r-tree[pos*2].l+1;
        tree[pos*2].lgt1=tree[pos*2].r-tree[pos*2].l+1;
        tree[pos*2+1].sum1=tree[pos*2+1].r-tree[pos*2+1].l+1;
        tree[pos*2+1].l1=tree[pos*2+1].r-tree[pos*2+1].l+1;
        tree[pos*2+1].r1=tree[pos*2+1].r-tree[pos*2+1].l+1;
        tree[pos*2+1].lgt1=tree[pos*2+1].r-tree[pos*2+1].l+1;

        tree[pos*2].sum0=0;
        tree[pos*2].l0=0;
        tree[pos*2].r0=0;
        tree[pos*2].lgt0=0;
        tree[pos*2+1].sum0=0;
        tree[pos*2+1].l0=0;
        tree[pos*2+1].r0=0;
        tree[pos*2+1].lgt0=0;

        tree[pos*2].laz1=1;
        tree[pos*2+1].laz1=1;
    }
    if(tree[pos].laz1==0){
        tree[pos*2].sum1=0;
        tree[pos*2].l1=0;
        tree[pos*2].r1=0;
        tree[pos*2].lgt1=0;
        tree[pos*2+1].sum1=0;
        tree[pos*2+1].l1=0;
        tree[pos*2+1].r1=0;
        tree[pos*2+1].lgt1=0;

        tree[pos*2].sum0=tree[pos*2].r-tree[pos*2].l+1;
        tree[pos*2].l0=tree[pos*2].r-tree[pos*2].l+1;
        tree[pos*2].r0=tree[pos*2].r-tree[pos*2].l+1;
        tree[pos*2].lgt0=tree[pos*2].r-tree[pos*2].l+1;
        tree[pos*2+1].sum0=tree[pos*2+1].r-tree[pos*2+1].l+1;
        tree[pos*2+1].l0=tree[pos*2+1].r-tree[pos*2+1].l+1;
        tree[pos*2+1].r0=tree[pos*2+1].r-tree[pos*2+1].l+1;
        tree[pos*2+1].lgt0=tree[pos*2+1].r-tree[pos*2+1].l+1;

        tree[pos*2].laz1=0;
        tree[pos*2+1].laz1=0;
    }
    tree[pos].laz1=-1;
    if(tree[pos].laz2==-1){
        swap(tree[pos*2].l0,tree[pos*2].l1);
        swap(tree[pos*2].r0,tree[pos*2].r1);
        swap(tree[pos*2].lgt0,tree[pos*2].lgt1);
        swap(tree[pos*2].sum0,tree[pos*2].sum1);

        swap(tree[pos*2+1].l0,tree[pos*2+1].l1);
        swap(tree[pos*2+1].r0,tree[pos*2+1].r1);
        swap(tree[pos*2+1].lgt0,tree[pos*2+1].lgt1);
        swap(tree[pos*2+1].sum0,tree[pos*2+1].sum1);

        tree[pos*2].laz2*=-1;
        tree[pos*2+1].laz2*=-1;
    }
    tree[pos].laz2=1;
}
void build(int pos,int lft,int rgt){
    tree[pos].l=lft;
    tree[pos].r=rgt;
    tree[pos].laz1=-1;
    tree[pos].laz2=1; 
    if(lft==rgt){
        if(a[lft]==1){
            tree[pos].sum1=1;
            tree[pos].l1=1;
            tree[pos].r1=1;
            tree[pos].lgt1=1;
        }else{
            tree[pos].sum0=1;
            tree[pos].l0=1;
            tree[pos].r0=1;
            tree[pos].lgt0=1;
        }
        return;
    }
    int mid=(lft+rgt)/2;
    build(pos*2,lft,mid);
    build(pos*2+1,mid+1,rgt);
    push_up(pos);
}
void fill1(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt){
        tree[pos].sum1=tree[pos].r-tree[pos].l+1;
        tree[pos].l1=tree[pos].r-tree[pos].l+1;
        tree[pos].r1=tree[pos].r-tree[pos].l+1;
        tree[pos].lgt1=tree[pos].r-tree[pos].l+1;

        tree[pos].sum0=0;
        tree[pos].l0=0;
        tree[pos].r0=0;
        tree[pos].lgt0=0;

        tree[pos].laz1=1;
        tree[pos].laz2=1;
        return;
    }
    if(tree[pos].r<lft||rgt<tree[pos].l) return;
    push_down(pos);
    fill1(pos*2,lft,rgt);
    fill1(pos*2+1,lft,rgt);
    push_up(pos);
}
void fill0(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt){
        tree[pos].sum0=tree[pos].r-tree[pos].l+1;
        tree[pos].l0=tree[pos].r-tree[pos].l+1;
        tree[pos].r0=tree[pos].r-tree[pos].l+1;
        tree[pos].lgt0=tree[pos].r-tree[pos].l+1;

        tree[pos].sum1=0;
        tree[pos].l1=0;
        tree[pos].r1=0;
        tree[pos].lgt1=0;

        tree[pos].laz1=0;
        tree[pos].laz2=1;
        return;
    }
    if(tree[pos].r<lft||rgt<tree[pos].l) return;
    push_down(pos);
    fill0(pos*2,lft,rgt);
    fill0(pos*2+1,lft,rgt);
    push_up(pos);
}
void rev(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt){
        swap(tree[pos].l0,tree[pos].l1);
        swap(tree[pos].r0,tree[pos].r1);
        swap(tree[pos].lgt0,tree[pos].lgt1);
        swap(tree[pos].sum0,tree[pos].sum1);
        tree[pos].laz2*=-1;
        return;
    }
    if(tree[pos].r<lft||rgt<tree[pos].l) return;
    push_down(pos);
    rev(pos*2,lft,rgt);
    rev(pos*2+1,lft,rgt);
    push_up(pos);
}
int ask1(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt) return tree[pos].sum1;
    if(tree[pos].r<lft||rgt<tree[pos].l) return 0;
    push_down(pos);
    return ask1(pos*2,lft,rgt)+ask1(pos*2+1,lft,rgt);
}
node ask2(int pos,int lft,int rgt){
    if(lft<=tree[pos].l&&tree[pos].r<=rgt) return tree[pos];
    push_down(pos);
    if(tree[pos*2].r<lft) return ask2(pos*2+1,lft,rgt);
    if(rgt<tree[pos*2+1].l) return ask2(pos*2,lft,rgt);
    int mid=(tree[pos].l+tree[pos].r)/2;
    node t1=ask2(pos*2,lft,rgt);
    node t2=ask2(pos*2+1,lft,rgt);
    node ans;
    ans.lgt1=max(t1.r1+t2.l1,max(t1.lgt1,t2.lgt1));
    ans.l1=t1.l1;
    ans.r1=t2.r1;
    if(t1.sum1==mid-tree[pos].l+1) ans.l1=t1.sum1+t2.l1;
    if(t2.sum1==tree[pos].r-mid) ans.r1=t2.sum1+t1.r1;
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    build(1,1,n);
    while(m--){
        int op,ll,rr;
        cin>>op>>ll>>rr;
        ll++;
        rr++;
        if(op==0) fill0(1,ll,rr);
        if(op==1) fill1(1,ll,rr);
        if(op==2) rev(1,ll,rr);
        if(op==3) cout<<ask1(1,ll,rr)<<endl;
        if(op==4) cout<<ask2(1,ll,rr).lgt1<<endl;
    }
    return 0;
}

by toolong114514 @ 2023-11-21 16:39:40

wssb,线段树下传覆盖懒标记时忘记清空集结点的反转懒标记了。此贴结。


by yugen @ 2024-04-18 13:47:50

@toolong114514 太感谢了,我也在这里出错了,改了代码从10pts变100pts了。


by immerse_23 @ 2024-06-07 17:04:05

草。最不爱数据结构的一集。


|