【题意】
读入比较麻烦,N≤1.1×106的01串,四种操作
F a b:[a, b]变为1E a b:[a, b]变为0
I a b:[a, b]01翻转,即0变1,1变0
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;
}