样例和input都过了还是0pts,寻遍了认识的巨佬都调不出来……

P2572 [SCOI2010] 序列操作

whileAK @ 2023-08-15 15:58:27

蒟蒻尝试的第二道紫题,至今快一个月了吧,还是0pts,故在此征求天下巨佬的意见,助我A掉线段树题单对线段树有更深的理解~~

#include<bits/stdc++.h>
using namespace std;
int n,q,a[100005];
struct tree { //sum:1的数量 l0:连续前缀0的长度 l1同理;r则为后缀长度;
    int ll,rr,sum,l0,l1,r0,r1,max0,max1,s,fan;//max0为最长连续0的长度,max1同理,s表示是否有覆盖操作,fan表示是否有区间取反
} t[400005];
void push_up(int p) {
    int mid=t[p].ll+t[p].rr>>1,l=t[p].ll,r=t[p].rr;
    t[p].sum=t[2*p].sum+t[2*p+1].sum;//父子节点转移
    t[p].l0=t[2*p].l0;
    if(t[p].l0==mid-l+1)t[p].l0+=t[2*p+1].l0;
    t[p].l1=t[2*p].l1;
    if(t[p].l1==mid-l+1)t[p].l1+=t[2*p+1].l1;
    t[p].r0=t[2*p+1].r0;
    if(t[p].r0==r-mid)t[p].r0+=t[2*p].r0;
    t[p].r1=t[2*p+1].r1;
    if(t[p].r1==r-mid)t[p].r1+=t[2*p].r1;
    t[p].max0=max(t[2*p].max0,t[2*p+1].max0);
    t[p].max0=max(t[p].max0,t[2*p].r0+t[2*p+1].l0);
    t[p].max1=max(t[2*p].max1,t[2*p+1].max1);
    t[p].max1=max(t[p].max1,t[2*p].r1+t[2*p+1].l1);
}//建树
void build(int l,int r,int p) {
    t[p].ll=l,t[p].rr=r;
    t[p].s=-1,t[p].fan=0;
    if(l==r) {
        t[p].sum=a[l];
        t[p].l0=t[p].max0=t[p].l1=t[p].max1=t[p].r0=t[p].r1=0;
        if(a[l]==0)t[p].l0=t[p].max0=t[p].r0=1;
        else t[p].l1=t[p].max1=t[p].r1=1;
        return;
    }
    int mid=l+r>>1;
    build(l,mid,2*p),build(mid+1,r,2*p+1);
    push_up(p);
}
void spread(int p) { //懒标记传递
    int x=t[2*p].ll,y=t[2*p].rr,c=t[2*p+1].ll,d=t[2*p+1].rr;
    if(t[p].s!=-1) {
        t[2*p].sum=t[p].s*(y-x+1);
        t[2*p+1].sum=t[p].s*(d-c+1);
        if(!t[p].s)t[2*p].l0=t[2*p].r0=t[2*p].max0=y-x+1,t[2*p].l1=t[2*p].r1=t[2*p].max1=0;
        else t[2*p].l0=t[2*p].r0=t[2*p].max0=0,t[2*p].l1=t[2*p].r1=t[2*p].max1=y-x+1;
        if(!t[p].s)t[2*p+1].l0=t[2*p+1].r0=t[2*p+1].max0=d-c+1,t[2*p+1].l1=t[2*p+1].r1=t[2*p+1].max1=0;
        else t[2*p+1].l0=t[2*p+1].r0=t[2*p+1].max0=0,t[2*p+1].l1=t[2*p+1].r1=t[2*p+1].max1=d-c+1;
        t[2*p].s=t[2*p+1].s=t[p].s;
        t[p].s=-1;
    }
    if(t[p].fan) {
        t[2*p].sum=x-y+1-t[2*p].sum;
        t[2*p+1].sum=d-c+1-t[2*p+1].sum;
        swap(t[2*p].l0,t[2*p].l1);
        swap(t[2*p].r0,t[2*p].r1);
        swap(t[2*p].max0,t[2*p].max1);
        swap(t[2*p+1].l0,t[2*p+1].l1);
        swap(t[2*p+1].r0,t[2*p+1].r1);
        swap(t[2*p+1].max0,t[2*p+1].max1);
        if(t[2*p].s!=-1)t[2*p].s^=1;
        else t[2*p].fan^=1;
        if(t[2*p+1].s!=-1)t[2*p+1].s^=1;
        else t[2*p+1].fan^=1;
        t[p].fan=0;
    }
}
void mend01(int l,int r,int z,int p) { //覆盖操作
    spread(p);
    if(t[p].ll>=l&&t[p].rr<=r) {
        t[p].sum=z*(t[p].rr-t[p].ll+1);
        if(!z) t[p].l0=t[p].r0=t[p].max0=t[p].rr-t[p].ll+1,t[p].l1=t[p].r1=t[p].max1=0;
        else t[p].l0=t[p].r0=t[p].max0=0,t[p].l1=t[p].r1=t[p].max1=t[p].rr-t[p].ll+1;
        t[p].s=z;
        t[p].fan=0;
        return;
    }
    int mid=t[p].ll+t[p].rr>>1;
    if(l<=mid)mend01(l,r,z,2*p);
    if(r>mid)mend01(l,r,z,2*p+1);
    push_up(p);
}
void mend_fan(int l,int r,int p) { //取反操作
    spread(p);
    if(t[p].ll>=l&&t[p].rr<=r) {
        t[p].sum=t[p].rr-t[p].ll+1-t[p].sum;
        swap(t[p].l0,t[p].l1);
        swap(t[p].r0,t[p].r1);
        swap(t[p].max0,t[p].max1);
        if(t[p].s!=-1)t[p].s^=1;
        else t[p].fan^1;
        return;
    }
    int mid=t[p].ll+t[p].rr>>1;
    if(l<=mid)mend_fan(l,r,2*p);
    if(r>mid)mend_fan(l,r,2*p+1);
    push_up(p);
}
int find_sum(int l,int r,int p) {
    spread(p);
    if(t[p].ll>=l&&t[p].rr<=r) {
        return t[p].sum;
    }
    int mid=t[p].ll+t[p].rr>>1,ans=0;
    if(l<=mid)ans+=find_sum(l,r,2*p);
    if(r>mid)ans+=find_sum(l,r,2*p+1);
    return ans;
}
int find_l1(int l,int r,int p) { //查询l~r的连续前缀1的长度
    spread(p);
    if(t[p].ll>=l&&t[p].rr<=r) { //cout<<"l1:"<<t[p].ll<<" r1:"<<t[p].rr<<" ans:"<<t[p].l1<<endl;
        return t[p].l1;
    }
    int mid=t[p].ll+t[p].rr>>1,ans=0;
    if(l<=mid) { //转移
        ans=find_l1(l,r,2*p);
        if(r>mid&&ans==mid-max(l,t[p].ll)+1)ans+=find_l1(l,r,2*p+1);
    } else ans+=find_l1(l,r,2*p+1); //cout<<"l1:"<<t[p].ll<<" r1:"<<t[p].rr<<" ans:"<<ans<<endl;
    return ans;
}
int find_r1(int l,int r,int p) { //查询l~r的连续后缀1的长度
    spread(p);
    if(t[p].ll>=l&&t[p].rr<=r) { //cout<<"ll0:"<<l<<" rr0:"<<r<<" ans:"<<t[p].r1<<endl;//cout<<"ll0:"<<t[p].ll<<" rr0:"<<t[p].rr<<endl;
        return t[p].r1;
    }
    int mid=t[p].ll+t[p].rr>>1,ans=0;
    if(r>mid) { //转移
        ans=find_r1(l,r,2*p+1);
        if(l<=mid&&ans==min(r,t[2*p+1].rr)-mid)ans+=find_r1(l,r,2*p);
    } else ans+=find_r1(l,r,2*p); //cout<<"l0:"<<l<<" r0:"<<r<<" ans:"<<ans<<endl;
    return ans;
}
int find_1(int l,int r,int p) { //查询最长连续1的长度
    spread(p);
    if(t[p].ll>=l&&t[p].rr<=r) { //cout<<"l:"<<t[p].ll<<" r:"<<t[p].rr<<" ans:"<<t[p].max1<<endl;
        return t[p].max1;
    }
    int mid=t[p].ll+t[p].rr>>1,ans=0,k;
    if(l<=mid) { //转移
        k=find_1(l,r,2*p);
        ans=max(ans,k);
    }
    if(r>mid) {
        k=find_1(l,r,2*p+1);
        ans=max(ans,k);
    }
    if(l<=mid&&r>mid) {
        int u=find_l1(mid+1,r,1),v=find_r1(l,mid,1);//cout<<"l1:"<<mid+1<<" r1:"<<t[p].rr<<" u:"<<u<<endl;
        ans=max(ans,u+v);//cout<<"l0:"<<t[p].ll<<" r0:"<<mid<<" v:"<<v<<endl;
    }//cout<<"l:"<<t[p].ll<<" r:"<<t[p].rr<<" ans:"<<ans<<endl;
    return ans;
}
int main() {
    scanf("%d%d",&n,&q);
    for(register int i(1); i<=n; ++i)scanf("%d",&a[i]);
    build(1,n,1);
    int op,x,y;
    while(q--) {
        scanf("%d%d%d",&op,&x,&y);
        ++x,++y;//输入下标以0开始,所以++;
        if(op==0||op==1) {
            mend01(x,y,op,1);
        }
        if(op==2) {
            mend_fan(x,y,1);
        }
        if(op==3) {
            printf("%d\n",find_sum(x,y,1));
        }
        if(op==4) {
            printf("%d\n",find_1(x,y,1));
        }
    }
    return 0;
}

by whileAK @ 2023-08-15 15:59:31

码风不正,请见谅~


by JT_dw_ @ 2023-08-26 21:36:49

@whileAK 对拍造的数据:

6 6
0 0 1 1 1 0 
2 3 6
4 1 4
1 1 4
0 3 4
3 2 2
2 5 6

out:
1
1

by whileAK @ 2023-08-27 18:14:58

也过了啊,还是0pts ……


|