五种操作,三种更新,两种查询,合并区间。。。算是比较经典的题目了,操作和查询都比较常规,合并的题目之前也写过几道。。。不过这道题目要用到两种lazy标记,因为异或和全为1,全为0不能合并成一种。。所以写pushdown和写updata的时候要小心,先全改,再异或,先异或,再全改,先异或再异或。。。几种情况都要考虑清楚,不然容易错。。。总的来说这道题目还是比较经典的。。。
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #define maxn 400005 #define eps 1e-6 #define mod 1000000007 #define INF 99999999 #define lowbit(x) (x&(-x)) #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; int mark1[maxn], mark2[maxn]; int sum[maxn], init[maxn]; int lmax[2][maxn], rmax[2][maxn]; int segmax[2][maxn], segnum[2][maxn]; int ansl[maxn], ansv[maxn]; int n, m, k; int ql, qr, ans; void pushup(int o, int L, int R, int c) { int tmp=0, mid=(L+R)>>1; if(rmax[c][o<<1] && lmax[c][o<<1 | 1]) tmp=rmax[c][o<<1]+lmax[c][o<<1 | 1]; if(tmp>=segmax[c][o<<1] && tmp>=segmax[c][o<<1 | 1]) segmax[c][o]=tmp, segnum[c][o]=mid-rmax[c][o<<1]+1; else if(segmax[c][o<<1]>segmax[c][o<<1 | 1]) segmax[c][o]=segmax[c][o<<1], segnum[c][o]=segnum[c][o<<1]; else segmax[c][o]=segmax[c][o<<1 | 1], segnum[c][o]=segnum[c][o<<1 | 1]; if(segnum[c][o]==L) lmax[c][o]=segmax[c][o]; else lmax[c][o]=lmax[c][o<<1]; if(segnum[c][o]+segmax[c][o]-1==R) rmax[c][o]=segmax[c][o]; else rmax[c][o]=rmax[c][o<<1 | 1]; sum[o]=sum[o<<1]+sum[o<<1 | 1]; } void build(int o, int L, int R) { if(L==R){ sum[o]=init[L]; if(init[L]){ segmax[0][o]=0, segmax[1][o]=1, segnum[0][o]=L, segnum[1][o]=L; lmax[0][o]=0, rmax[0][o]=0, lmax[1][o]=1, rmax[1][o]=1; } else{ segmax[0][o]=1, segmax[1][o]=0, segnum[0][o]=L, segnum[1][o]=L; lmax[0][o]=1, rmax[0][o]=1, lmax[1][o]=0, rmax[1][o]=0; } return; } int mid=(R+L)>>1; build(lson); build(rson); pushup(o, L, R, 0); pushup(o, L, R, 1); } void pushdown1(int o, int L, int R) { if(mark1[o]==-1) return; int mid=(R+L)>>1; if(mark1[o]==0){ segnum[0][o<<1]=L, segnum[0][o<<1 | 1]=mid+1; lmax[0][o<<1]=rmax[0][o<<1]=segmax[0][o<<1]=mid-L+1; lmax[0][o<<1 | 1]=rmax[0][o<<1 | 1]=segmax[0][o<<1 | 1]=R-mid; segnum[1][o<<1]=L, segnum[1][o<<1 | 1]=mid+1; lmax[1][o<<1]=rmax[1][o<<1]=segmax[1][o<<1]=0; lmax[1][o<<1 | 1]=rmax[1][o<<1 | 1]=segmax[1][o<<1 | 1]=0; sum[o<<1]=sum[o<<1 | 1]=0; } else{ segnum[1][o<<1]=L, segnum[1][o<<1 | 1]=mid+1; lmax[1][o<<1]=rmax[1][o<<1]=segmax[1][o<<1]=mid-L+1; lmax[1][o<<1 | 1]=rmax[1][o<<1 | 1]=segmax[1][o<<1 | 1]=R-mid; segnum[0][o<<1]=L, segnum[0][o<<1 | 1]=mid+1; lmax[0][o<<1]=rmax[0][o<<1]=segmax[0][o<<1]=0; lmax[0][o<<1 | 1]=rmax[0][o<<1 | 1]=segmax[0][o<<1 | 1]=0; sum[o<<1]=mid-L+1, sum[o<<1 | 1]=R-mid; } mark1[o<<1]=mark1[o<<1 | 1]=mark1[o]; mark1[o]=-1, mark2[o]=0; } void pushdown2(int o, int L, int R) { if(!mark2[o]) return; int mid=(R+L)>>1; swap(lmax[0][o<<1], lmax[1][o<<1]), swap(lmax[0][o<<1 | 1], lmax[1][o<<1 | 1]); swap(rmax[0][o<<1], rmax[1][o<<1]), swap(rmax[0][o<<1 | 1], rmax[1][o<<1 | 1]); swap(segmax[0][o<<1], segmax[1][o<<1]), swap(segmax[0][o<<1 | 1], segmax[1][o<<1 | 1]); swap(segnum[0][o<<1], segnum[1][o<<1]), swap(segnum[0][o<<1 | 1], segnum[1][o<<1 | 1]); sum[o<<1]=mid-L+1-sum[o<<1], sum[o<<1 | 1]=R-mid-sum[o<<1 | 1]; if(mark1[o<<1]!=-1) mark1[o<<1]^=1, mark2[o<<1]=0; else mark2[o<<1]^=1; if(mark1[o<<1 | 1]!=-1) mark1[o<<1 | 1]^=1, mark2[o<<1 | 1]=0; else mark2[o<<1 | 1]^=1; mark2[o]=0; } void updata(int o, int L, int R) { if(ql<=L && qr>=R){ if(k==1){ mark1[o]=0, mark2[o]=0; segnum[0][o]=segnum[1][o]=L, sum[o]=0; lmax[0][o]=rmax[0][o]=segmax[0][o]=R-L+1; lmax[1][o]=rmax[1][o]=segmax[1][o]=0; } if(k==2){ mark1[o]=1, mark2[o]=0; segnum[0][o]=segnum[1][o]=L, sum[o]=R-L+1; lmax[0][o]=rmax[0][o]=segmax[0][o]=0; lmax[1][o]=rmax[1][o]=segmax[1][o]=R-L+1; } if(k==3){ if(mark1[o]!=-1) mark1[o]^=1; else mark2[o]^=1; sum[o]=R-L+1-sum[o]; swap(segmax[0][o], segmax[1][o]); swap(segnum[0][o], segnum[1][o]); swap(lmax[0][o], lmax[1][o]); swap(rmax[0][o], rmax[1][o]); } return; } pushdown2(o, L, R); pushdown1(o, L, R); int mid=(R+L)>>1; if(ql<=mid) updata(lson); if(qr>mid) updata(rson); pushup(o, L, R, 0); pushup(o, L, R, 1); } void _query(int o, int L, int R) { if(ql<=L && qr>=R){ ans+=sum[o]; return; } pushdown2(o, L, R); pushdown1(o, L, R); int mid=(R+L)>>1; if(ql<=mid) _query(lson); if(qr>mid) _query(rson); pushup(o, L, R, 0); pushup(o, L, R, 1); } void _pushup(int o, int L, int R) { int mid=(R+L)>>1, tmp=0; if(ql>mid || qr<=mid || !lmax[1][o<<1 | 1] || !rmax[1][o<<1]) tmp=0; else tmp=min(mid+lmax[1][o<<1 | 1], qr)-max(mid-rmax[1][o<<1]+1, ql)+1; if(tmp>=ansv[o<<1] && tmp>=ansv[o<<1 | 1]) ansv[o]=tmp, ansl[o]=max(mid-rmax[1][o<<1]+1, ql); else if(ansv[o<<1]>ansv[o<<1 | 1]) ansv[o]=ansv[o<<1], ansl[o]=ansl[o<<1]; else ansv[o]=ansv[o<<1 | 1], ansl[o]=ansl[o<<1 | 1]; ansl[o<<1]=ansl[o<<1 | 1]=ansv[o<<1]=ansv[o<<1 | 1]=0; } void query(int o, int L, int R) { if(ql<=L && qr>=R){ ansl[o]=segnum[1][o], ansv[o]=segmax[1][o]; return; } pushdown2(o, L, R); pushdown1(o, L, R); int mid=(R+L)>>1; if(ql<=mid) query(lson); if(qr>mid) query(rson); pushup(o, L, R, 0); pushup(o, L, R, 1); _pushup(o, L, R); } void solve(void) { while(m--){ scanf("%d%d%d",&k,&ql,&qr); k++, ql++, qr++; if(k>=4){ ans=0; if(k==4){ _query(1, 1, n); printf("%d\n", ans); } else{ query(1, 1, n); printf("%d\n", ansv[1]); } } else updata(1, 1, n); } } int main(void) { int _; while(scanf("%d",&_)!=EOF){ while(_--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&init[i]); memset(mark1, -1, sizeof mark1); memset(mark2, 0, sizeof mark2); memset(ansl, 0, sizeof ansl); memset(ansv, 0, sizeof ansv); build(1, 1, n); solve(); } } return 0; }