【题意】
读入比较麻烦,N≤1.1×106的01串,四种操作
F a b:[a, b]变为1
S a b:[a, b]中1有多少个
【分析】很久之前就碰到这种问题了,直到今天才学会这种问题!其实这道题只需要在普通的延迟标记的姿势上合并标记,根据标记值更新当前的答案,今天学习了这种新姿势。
别忘了更新的时候合并标记!以后碰到这样的问题一定要做出来QAQ,这里还有个坑,在我代码的注释部分有说明!
【AC代码】
#include <map> #include <set> #include <queue> #include <vector> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int maxn = 1000005; string s; struct node{ int l,r,sum;//sum记录区间里1的个数 }Tree[maxn<<2]; int tag[maxn<<2]; void Push_Up(int rt){ Tree[rt].sum = Tree[rt<<1].sum+Tree[rt<<1|1].sum; } void Change_Tag(int fa,int &son){//这里的son一定要传引用,因为他自己要被更新的,不然错了 if(fa==2){ son = 1-son; }else son = fa; } void Push_Down(int rt){ if(tag[rt]!=-1){ int len1 = Tree[rt<<1].r - Tree[rt<<1].l + 1; int len2 = Tree[rt<<1|1].r - Tree[rt<<1|1].l + 1; if(tag[rt]==-1){ Tree[rt<<1].sum = Tree[rt<<1].sum; Tree[rt<<1|1].sum = Tree[rt<<1|1].sum; } else if(tag[rt]==2){ Tree[rt<<1].sum = len1 - Tree[rt<<1].sum; Tree[rt<<1|1].sum = len2 - Tree[rt<<1|1].sum; }else{ Tree[rt<<1].sum = tag[rt]*len1; Tree[rt<<1|1].sum = tag[rt]*len2; } Change_Tag(tag[rt],tag[rt<<1]); Change_Tag(tag[rt],tag[rt<<1|1]); tag[rt]=-1; } } void Build(int l,int r,int rt){ Tree[rt].l=l,Tree[rt].r=r; tag[rt]=-1; if(l==r){ Tree[rt].sum = s[l]-'0'; return ; } int m = (Tree[rt].l+Tree[rt].r)>>1; Build(l,m,rt<<1); Build(m+1,r,rt<<1|1); Push_Up(rt); } void Update(int L,int R,int v,int rt){ if(L<=Tree[rt].l&&Tree[rt].r<=R){ int len = Tree[rt].r-Tree[rt].l+1; if(v==-1) Tree[rt].sum = Tree[rt].sum; else if(v==2) Tree[rt].sum = len-Tree[rt].sum; else Tree[rt].sum = v*len; Change_Tag(v,tag[rt]); return ; } Push_Down(rt); int m = (Tree[rt].l+Tree[rt].r)>>1; if(L<=m) Update(L,R,v,rt<<1); if(m<R) Update(L,R,v,rt<<1|1); Push_Up(rt); } int query_ans(int L,int R,int rt){ if(L<=Tree[rt].l&&Tree[rt].r<=R) return Tree[rt].sum; Push_Down(rt); int m = (Tree[rt].l+Tree[rt].r)>>1; int ret = 0; if(L<=m) ret+=query_ans(L,R,rt<<1); if(m<R) ret+=query_ans(L,R,rt<<1|1); return ret; } int main(){ int T,ncase=1; scanf("%d",&T); while(T--){ s.clear(); int n,m,q,L,R; scanf("%d",&n); while(n--){ char buf[105]; scanf("%d%s",&m,buf); while(m--){ s+=buf; } } Build(0,s.size()-1,1); printf("Case %d:\n",ncase++); int cnt=1; char op[2]; scanf("%d",&q); while(q--){ scanf("%s%d%d",op,&L,&R); if(op[0]=='F') Update(L,R,1,1); else if(op[0]=='E') Update(L,R,0,1); else if(op[0]=='I') Update(L,R,2,1); else printf("Q%d: %d\n",cnt++,query_ans(L,R,1)); } } return 0; }