如果你想赤石分块0pts炫观球跳

P2572 [SCOI2010] 序列操作

wuhuhuhuhuhuhu @ 2024-10-25 14:55:13

#include<bits/stdc++.h>
using namespace std;
struct kuai {
    long long zhi=0;
    long long l=0;
    long long r=0;
    long long llian1=0;
    long long rlian1=0;
    long long lian1=0;
    long long llian0=0;
    long long rlian0=0;
    long long lian0=0;
};
long long meikuai;
kuai block[1000005];
long long c[1000005];
long long lan[1000005];
vector<long long> lan0(1000005,2);
inline long long getkuai(long long x) {
    return (x-1)/meikuai+1;
}
inline void push(long long x) {
    for(long long n=block[x].l; n<=block[x].r; n++) {
        if(lan0[x]==2) c[n]=(c[n]^lan[x]);
        else if(lan0[x]==0) c[n]=(c[n]&0);
        else if(lan0[x]==1) c[n]=(c[n]|1);
    }
    lan0[x]=2;
    lan[x]=0;
}
inline void weihu(long long x) {
    push(x);
    long long cnt=0;
    for(long long i=block[x].l; i<=block[x].r; i++) {
        if(c[i]==1) {
            block[x].lian0=max(block[x].lian0,cnt);
            cnt=0;
        } else cnt++;
    }
    block[x].lian0=max(block[x].lian0,cnt);
    cnt=0;
    for(long long i=block[x].l; i<=block[x].r; i++) {
        if(c[i]==0) {
            block[x].lian1=max(block[x].lian1,cnt);
            cnt=0;
        } else cnt++;
    }
    block[x].lian1=max(block[x].lian1,cnt);
    cnt=0;
    long long f0=0,f1=0,cnt1=0;
    for(long long i=block[x].l; i<=block[x].r; i++) {
        if(c[i]==0) {
            if(f0==0) cnt++;
            block[x].llian1=max(block[x].llian1,cnt1);
            cnt1=0;
            f1=1;
        }
        if(c[i]==1) {
            if(f1==0) cnt1++;
            block[x].llian0=max(block[x].llian0,cnt);
            cnt=0;
            f0=1;
        }
        if(f0==1&&f1==1) break;
    }
    block[x].llian1=max(block[x].llian1,cnt1);
    block[x].llian0=max(block[x].llian0,cnt);
    f0=0,f1=0,cnt1=0,cnt=0;
    for(long long i=block[x].r; i>=block[x].l; i--) {
        if(c[i]==0) {
            if(f0==0) cnt++;
            block[x].rlian1=max(block[x].rlian1,cnt1);
            cnt1=0;
            f1=1;
        }
        if(c[i]==1) {
            if(f1==0) cnt1++;
            block[x].rlian0=max(cnt,block[x].rlian0);
            cnt=0;
            f0=1;
        }
        if(f0==1&&f1==1) break;
    }
    block[x].rlian1=max(block[x].rlian1,cnt1);
    block[x].rlian0=max(cnt,block[x].rlian0);
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    long long a,b;
    cin>>a>>b;
    for(long long i=1; i<=a; i++) {
        cin>>c[i];
    }
    meikuai=(long long)sqrt(a);
    long long sum=0,cnt=1;
    for(long long i=1; i<=a; i++) {
        sum+=c[i];
        if(i%meikuai==0) {
            block[cnt].zhi=sum;
            block[cnt].l=block[cnt-1].r+1;
            block[cnt].r=i;
            sum=0;
            weihu(cnt);
            cnt++;
        }
    }
    if(a%((long long)sqrt(a))!=0) {
        block[cnt].zhi=sum;
        block[cnt].l=block[cnt-1].r+1;
        block[cnt].r=a;
    }
    weihu(cnt);
    long long ji;
    long long quel,quer,lid,rid;
    for(long long i=0; i<b; i++) {
        cin>>ji;
        cin>>quel>>quer;
        quel++;
        quer++;
        lid=getkuai(quel);
        rid=getkuai(quer);
        if(ji==0) {
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(c[n]==1) {
                        block[lid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(lid);
            } else {
                for(long long n=quel; n<=block[lid].r; n++) {
                    if(c[n]==1) {
                        block[lid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(lid);
                for(long long n=lid+1; n<rid; n++) {
                    block[n].zhi=0;
                    block[n].lian0=block[n].r-block[n].l+1;
                    block[n].llian0=block[n].lian0;
                    block[n].rlian0=block[n].lian0;
                    block[n].lian1=0;
                    block[n].llian1=0;
                    block[n].rlian1=0;
                    lan0[n]=0;
                    lan[n]=0;
                }
                for(long long n=block[rid].l; n<=quer; n++) {
                    if(c[n]==1) {
                        block[rid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(rid);
            }
        }
        if(ji==1) {
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(c[n]==0) {
                        block[lid].zhi++;
                        c[n]=1;
                    }
                }
                weihu(lid);
            } else {
                for(long long n=quel; n<=block[lid].r; n++) {
                    if(c[n]==0) {
                        block[lid].zhi++;
                        c[n]=1;
                    }
                }
                weihu(lid);
                for(long long n=lid+1; n<rid; n++) {
                    lan0[n]=1;
                    block[n].zhi=block[n].r-block[n].l+1;
                    lan[n]=0;
                    block[n].lian1=block[n].r-block[n].l+1;
                    block[n].llian1=block[n].lian1;
                    block[n].rlian1=block[n].lian1;
                    block[n].lian0=0;
                    block[n].llian0=0;
                    block[n].rlian0=0;
                }
                for(long long n=block[rid].l; n<=quer; n++) {
                    if(c[n]==0) {
                        block[rid].zhi++;
                        c[n]=1;
                    }
                }
                weihu(rid);
            }
        }
        if(ji==2) {
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(c[n]==0) {
                        block[lid].zhi++;
                        c[n]=1;
                    } else if(c[n]==1) {
                        block[lid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(lid);
            } else {
                for(long long n=quel; n<=block[lid].r; n++) {
                    if(c[n]==0) {
                        block[lid].zhi++;
                        c[n]=1;
                    } else if(c[n]==1) {
                        block[lid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(lid);
                for(long long n=lid+1; n<rid; n++) {
                    if(lan0[n]==2) lan[n]=lan[n]^1;
                    else lan0[n]=lan0[n]^1;
                    swap(block[n].lian0,block[n].lian1);
                    swap(block[n].llian0,block[n].llian1);
                    swap(block[n].rlian0,block[n].rlian1);
                }
                for(long long n=block[rid].l; n<=quer; n++) {
                    if(c[n]==0) {
                        block[rid].zhi++;
                        c[n]=1;
                    } else if(c[n]==1) {
                        block[rid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(rid);
            }
        }
        if(ji==3) {
            sum=0;
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(lan0[lid]==2) sum+=(c[n]^lan[lid]);
                    else if(lan0[lid]==0) sum+=(c[n]&lan0[lid]);
                    else if(lan0[lid]==1) sum+=(c[n]|lan0[lid]);
                }
            } else {
                for(long long n=quel; n<=block[lid].r; n++) {
                    if(lan0[lid]==2) sum+=(c[n]^lan[lid]);
                    else if(lan0[lid]==0) sum+=(c[n]&lan0[lid]);
                    else if(lan0[lid]==1) sum+=1;
                }
                for(long long n=lid+1; n<rid; n++) {
                    if(lan0[n]==2) {
                        if(lan[n]==1) sum+=block[n].r-block[n].l+1-block[n].zhi;
                        else sum+=block[n].zhi;
                    } else {
                        if(lan0[n]==1) sum+=block[n].r-block[n].l+1;
                    }
                }
                for(long long n=block[rid].l; n<=quer; n++) {
                    if(lan0[rid]==2) sum+=(c[n]^lan[rid]);
                    else if(lan0[rid]==0) sum+=(c[n]&lan0[rid]);
                    else if(lan0[rid]==1) sum+=1;
                }
            }
            cout<<sum<<endl;
        }
        if(ji==4) {
            weihu(lid);
            sum=0;
            cnt=0;
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(c[n]==0) {
                        sum=max(sum,cnt);
                        cnt=0;
                    } else cnt++;
                }
                sum=max(sum,cnt);
            } else {
                weihu(rid);
                sum=max(min(block[lid].rlian1,block[lid].r-quel+1)+min(block[lid+1].llian1,quer-block[lid+1].l+1),sum);
                for(long long n=lid+1; n<rid; n++) {
                    sum=max(block[n].rlian1+min(quer-block[n+1].l+1,block[n+1].llian1),max(block[n].lian1,sum));
                }
            }
            cout<<sum<<endl;
        }
    }
    return 0;
}

by wjr_jok @ 2024-10-25 15:11:01

@wuhuhuhuhuhuhu 思路?


by wuhuhuhuhuhuhu @ 2024-10-25 15:28:51

@wjr_jok 维护每块包含左端点的最长0/1 包含右端点的最长0/1 块内最长0/1


by wjr_jok @ 2024-10-25 15:44:18

@wuhuhuhuhuhuhu 能不能注释一下每一步的操作和变量的作用


by wuhuhuhuhuhuhu @ 2024-10-25 15:49:27

@wjr_jok 稍等


by wuhuhuhuhuhuhu @ 2024-10-25 16:03:30

#include<bits/stdc++.h>
using namespace std;
struct kuai {
    long long zhi=0;//每块1的个数 
    long long l=0;
    long long r=0;
    long long llian1=0;//包含左端点连续1 
    long long rlian1=0;//包含右端点连续1 
    long long lian1=0;//块内最长连续1 
    long long llian0=0; //包含左端点连续0
    long long rlian0=0;//包含右端点连续0
    long long lian0=0;//块内最长连续0 
};
long long meikuai;//每块长度 
kuai block[1000005]; //块 
long long c[1000005];//原数组 
long long lan[1000005];//反转标记 
vector<long long> lan0(1000005,2);//覆盖标记 
inline long long getkuai(long long x) {
    return (x-1)/meikuai+1;
}
inline void push(long long x) {
    for(long long n=block[x].l; n<=block[x].r; n++) {    //下放标记 
        if(lan0[x]==2) c[n]=(c[n]^lan[x]);
        else if(lan0[x]==0) c[n]=(c[n]&0);
        else if(lan0[x]==1) c[n]=(c[n]|1);
    }
    lan0[x]=2;
    lan[x]=0;
}
inline void weihu(long long x) {
    push(x);
    long long cnt=0;
    for(long long i=block[x].l; i<=block[x].r; i++) {   //计算块内最长连续0 
        if(c[i]==1) {
            block[x].lian0=max(block[x].lian0,cnt);
            cnt=0;
        } else cnt++;
    }
    block[x].lian0=max(block[x].lian0,cnt);
    cnt=0;
    for(long long i=block[x].l; i<=block[x].r; i++) { //计算块内最长连续1 
        if(c[i]==0) {
            block[x].lian1=max(block[x].lian1,cnt);
            cnt=0;
        } else cnt++;
    }
    block[x].lian1=max(block[x].lian1,cnt);
    cnt=0;
    long long f0=0,f1=0,cnt1=0;
    for(long long i=block[x].l; i<=block[x].r; i++) {//计算包含左端点连续1,0
        if(c[i]==0) {
            if(f0==0) cnt++;
            block[x].llian1=max(block[x].llian1,cnt1);
            cnt1=0;
            f1=1;
        }
        if(c[i]==1) {
            if(f1==0) cnt1++;
            block[x].llian0=max(block[x].llian0,cnt);
            cnt=0;
            f0=1;
        }
        if(f0==1&&f1==1) break;
    }
    block[x].llian1=max(block[x].llian1,cnt1);
    block[x].llian0=max(block[x].llian0,cnt);
    f0=0,f1=0,cnt1=0,cnt=0;
    for(long long i=block[x].r; i>=block[x].l; i--) {  //计算包含右端点连续1,0
        if(c[i]==0) {
            if(f0==0) cnt++;
            block[x].rlian1=max(block[x].rlian1,cnt1);
            cnt1=0;
            f1=1;
        }
        if(c[i]==1) {
            if(f1==0) cnt1++;
            block[x].rlian0=max(cnt,block[x].rlian0);
            cnt=0;
            f0=1;
        }
        if(f0==1&&f1==1) break;
    }
    block[x].rlian1=max(block[x].rlian1,cnt1);
    block[x].rlian0=max(cnt,block[x].rlian0);
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    long long a,b;
    cin>>a>>b;
    for(long long i=1; i<=a; i++) {
        cin>>c[i];
    }
    meikuai=(long long)sqrt(a);
    long long sum=0,cnt=1;
    for(long long i=1; i<=a; i++) {     //预处理每块 
        sum+=c[i];
        if(i%meikuai==0) {
            block[cnt].zhi=sum;
            block[cnt].l=block[cnt-1].r+1;
            block[cnt].r=i;
            sum=0;
            weihu(cnt);
            cnt++;
        }
    }
    if(a%((long long)sqrt(a))!=0) {
        block[cnt].zhi=sum;
        block[cnt].l=block[cnt-1].r+1;
        block[cnt].r=a;
    }
    weihu(cnt);
    long long ji;
    long long quel,quer,lid,rid;
    for(long long i=0; i<b; i++) {
        cin>>ji;
        cin>>quel>>quer;
        quel++;
        quer++;
        lid=getkuai(quel);
        rid=getkuai(quer);
        if(ji==0) {
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {   //在同一块暴力,下同 
                    if(c[n]==1) {
                        block[lid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(lid); 
            } else {
                for(long long n=quel; n<=block[lid].r; n++) { 
                    if(c[n]==1) {
                        block[lid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(lid);
                for(long long n=lid+1; n<rid; n++) {
                    block[n].zhi=0;
                    block[n].lian0=block[n].r-block[n].l+1;//中间块覆盖标记变为0,去掉反转标记 
                    block[n].llian0=block[n].lian0;
                    block[n].rlian0=block[n].lian0;
                    block[n].lian1=0;
                    block[n].llian1=0;
                    block[n].rlian1=0;
                    lan0[n]=0;
                    lan[n]=0;
                }
                for(long long n=block[rid].l; n<=quer; n++) {
                    if(c[n]==1) {
                        block[rid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(rid);
            }
        }
        if(ji==1) {
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(c[n]==0) {
                        block[lid].zhi++;
                        c[n]=1;
                    }
                }
                weihu(lid);
            } else {
                for(long long n=quel; n<=block[lid].r; n++) {
                    if(c[n]==0) {
                        block[lid].zhi++;
                        c[n]=1;
                    }
                }
                weihu(lid);
                for(long long n=lid+1; n<rid; n++) {
                    lan0[n]=1;
                    block[n].zhi=block[n].r-block[n].l+1;//中间块覆盖标记变为1,去掉反转标记 
                    lan[n]=0;
                    block[n].lian1=block[n].r-block[n].l+1;
                    block[n].llian1=block[n].lian1;
                    block[n].rlian1=block[n].lian1;
                    block[n].lian0=0;
                    block[n].llian0=0;
                    block[n].rlian0=0;
                }
                for(long long n=block[rid].l; n<=quer; n++) {
                    if(c[n]==0) {
                        block[rid].zhi++;
                        c[n]=1;
                    }
                }
                weihu(rid);
            }
        }
        if(ji==2) {
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(c[n]==0) {
                        block[lid].zhi++;
                        c[n]=1;
                    } else if(c[n]==1) {
                        block[lid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(lid);
            } else {
                for(long long n=quel; n<=block[lid].r; n++) {
                    if(c[n]==0) {
                        block[lid].zhi++;
                        c[n]=1;
                    } else if(c[n]==1) {
                        block[lid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(lid);
                for(long long n=lid+1; n<rid; n++) {
                    if(lan0[n]==2) lan[n]=lan[n]^1;//中间块覆盖标记反转,无覆盖标记就反转标记反转 
                    else lan0[n]=lan0[n]^1;
                    swap(block[n].lian0,block[n].lian1);//块内最长连续1与最长连续0交换 
                    swap(block[n].llian0,block[n].llian1);//包含左端点连续1的个数变成了连续0的个数 
                    swap(block[n].rlian0,block[n].rlian1);//右端点同理 
                }
                for(long long n=block[rid].l; n<=quer; n++) {
                    if(c[n]==0) {
                        block[rid].zhi++;
                        c[n]=1;
                    } else if(c[n]==1) {
                        block[rid].zhi--;
                        c[n]=0;
                    }
                }
                weihu(rid);
            }
        }
        if(ji==3) {
            sum=0;
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(lan0[lid]==2) sum+=(c[n]^lan[lid]);
                    else if(lan0[lid]==0) sum+=(c[n]&lan0[lid]);
                    else if(lan0[lid]==1) sum+=(c[n]|lan0[lid]);
                }
            } else {
                for(long long n=quel; n<=block[lid].r; n++) {
                    if(lan0[lid]==2) sum+=(c[n]^lan[lid]);
                    else if(lan0[lid]==0) sum+=(c[n]&lan0[lid]);
                    else if(lan0[lid]==1) sum+=1;
                }
                for(long long n=lid+1; n<rid; n++) {
                    if(lan0[n]==2) {
                        if(lan[n]==1) sum+=block[n].r-block[n].l+1-block[n].zhi;//中间块如果有反转标记0的个数就是1的个数 
                        else sum+=block[n].zhi;//没有直接加上1的个数 
                    } else {
                        if(lan0[n]==1) sum+=block[n].r-block[n].l+1;//有覆盖标记直接加上块长 
                    }
                }
                for(long long n=block[rid].l; n<=quer; n++) {
                    if(lan0[rid]==2) sum+=(c[n]^lan[rid]);
                    else if(lan0[rid]==0) sum+=(c[n]&lan0[rid]);
                    else if(lan0[rid]==1) sum+=1;
                }
            }
            cout<<sum<<endl;
        }
        if(ji==4) {
            weihu(lid);
            sum=0;
            cnt=0;
            if(lid==rid) {
                for(long long n=quel; n<=quer; n++) {
                    if(c[n]==0) {
                        sum=max(sum,cnt);
                        cnt=0;
                    } else cnt++;
                }
                sum=max(sum,cnt);
            } else {
                weihu(rid);
                sum=max(min(block[lid].rlian1,block[lid].r-quel+1)+min(block[lid+1].llian1,quer-block[lid+1].l+1),sum); 
                for(long long n=lid+1; n<rid; n++) {//不超出询问左块,用包含右端点最长1加上右块包含左端点最长1,,,,与块内最长1取最大 
                    sum=max(block[n].rlian1+min(quer-block[n+1].l+1,block[n+1].llian1),max(block[n].lian1,sum));
                }
            }
            cout<<sum<<endl;
        }
    }
    return 0;
}

@wjr_jok


|