Sequence operation
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6270 Accepted Submission(s): 1862
Problem Description
lxhgww got a sequence contains n characters which are all ‘0‘s or ‘1‘s.
We have five operations here:
Change operations:
0 a b change all characters into ‘0‘s in [a , b]
1 a b change all characters into ‘1‘s in [a , b]
2 a b change all ‘0‘s into ‘1‘s and change all ‘1‘s into ‘0‘s in [a, b]
Output operations:
3 a b output the number of ‘1‘s in [a, b]
4 a b output the length of the longest continuous ‘1‘ string in [a , b]
Input
T(T<=10) in the first line is the case number.
Each case has two integers in the first line: n and m (1 <= n , m <= 100000).
The next line contains n characters, ‘0‘ or ‘1‘ separated by spaces.
Then m lines are the operations:
op a b: 0 <= op <= 4 , 0 <= a <= b < n.
Output
For each output operation , output the result.
Sample Input
1 10 10 0 0 0 1 1 0 1 0 1 1 1 0 2 3 0 5 2 2 2 4 0 4 0 3 6 2 3 7 4 2 8 1 0 5 0 5 6 3 3 9
Sample Output
5 2 6 5
———————————————————————分割线————————————————
题目大意:
给定一个n个数的序列,有5种操作
1: 0 a b 将区间[a,b]覆盖为0
2:1 a b 将区间[a,b]覆盖为1
3:2 a b 将区间[a,b] 0变成1,1变成0
4:3 a b 查询区间[a,b]1的个数
5:4 a b 查询区间[a,b]连续1的个数
思路:
push_up 维护:
左连续,右连续,总连续的0/1的个数
总的1的个数
push_down lazy标记:
覆盖标记,异或标记
当某节点的信息被修改时,要push_up,对于异或标记和覆盖标记 要优先考虑覆盖标记,再考虑异或标记
查找区间的时候要push_down
细节好重要!!!加深理解push_up,push_down
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> const int maxn=100001; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; int lc[maxn<<2],rc[maxn<<2],mc[maxn<<2]; int lc0[maxn<<2],rc0[maxn<<2],mc0[maxn<<2]; int cov[maxn<<2],Xor[maxn<<2],sum[maxn<<2]; void f_xor(int rt,int m) { if(cov[rt]!=-1) cov[rt]^=1; else Xor[rt]^=1; swap(lc[rt],lc0[rt]); swap(rc[rt],rc0[rt]); swap(mc[rt],mc0[rt]); sum[rt]=m-sum[rt]; } void f_cov(int rt,int m,int c) { cov[rt]=c; Xor[rt]=0; lc0[rt]=rc0[rt]=mc0[rt]=c ?0:m; lc[rt]=rc[rt]=mc[rt]=sum[rt]=c ? m:0; } void push_down(int rt,int m) { if(cov[rt]!=-1) { f_cov(rt<<1,m-(m>>1),cov[rt]); f_cov(rt<<1|1,m>>1,cov[rt]); cov[rt]=-1; Xor[rt]=0; } if(Xor[rt]) { f_xor(rt<<1,m-(m>>1)); f_xor(rt<<1|1,m>>1); Xor[rt]=0; } } void push_up(int rt,int m) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; lc[rt]=lc[rt<<1]; rc[rt]=rc[rt<<1|1]; if(lc[rt]==m-(m>>1)) lc[rt]+=lc[rt<<1|1]; if(rc[rt]==m>>1) rc[rt]+=rc[rt<<1]; mc[rt]=max(rc[rt<<1]+lc[rt<<1|1],max(mc[rt<<1],mc[rt<<1|1])); lc0[rt]=lc0[rt<<1]; rc0[rt]=rc0[rt<<1|1]; if(lc0[rt]==m-(m>>1)) lc0[rt]+=lc0[rt<<1|1]; if(rc0[rt]==m>>1) rc0[rt]+=rc0[rt<<1]; mc0[rt]=max(lc0[rt<<1|1]+rc0[rt<<1],max(mc0[rt<<1],mc0[rt<<1|1])); } void build(int l,int r,int rt) { cov[rt]=-1; Xor[rt]=0; if(l==r) { scanf("%d",&sum[rt]); cov[rt]=lc[rt]=rc[rt]=mc[rt]=sum[rt]; lc0[rt]=rc0[rt]=mc0[rt]= 1-sum[rt]; return ; } int m=(l+r)>>1; build(lson); build(rson); push_up(rt,r-l+1); } void update(int op,int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { if(op==0) f_cov(rt,r-l+1,0); if(op==1) f_cov(rt,r-l+1,1); if(op==2) f_xor(rt,r-l+1); return ; } push_down(rt,r-l+1); int m=(l+r)>>1; if(L<=m) update(op,L,R,lson); if(m<R) update(op,L,R,rson); push_up(rt,r-l+1); } int query_sum(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return sum[rt]; } push_down(rt,r-l+1); int m=(l+r)>>1; int ans=0; if(L<=m) ans+=query_sum(L,R,lson); if(m<R) ans+=query_sum(L,R,rson); return ans; } int query_len(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return mc[rt]; } push_down(rt,r-l+1); int m=(l+r)>>1; int ans=0; if(L<=m) ans=max(ans,query_len(L,R,lson)); if(m<R) ans=max(ans,query_len(L,R,rson)); return max(ans,min(m-L+1,rc[rt<<1])+min(R-m,lc[rt<<1|1])); } int main() { int T,n,m; cin>>T; while(T--) { scanf("%d %d",&n,&m); build(0,n-1,1); int op,l,r; while(m--) { scanf("%d %d %d",&op,&l,&r); if(op<=2) update(op,l,r,0,n-1,1); if(op==3) printf("%d\n",query_sum(l,r,0,n-1,1)); if(op==4) printf("%d\n",query_len(l,r,0,n-1,1)); } } return 0; }