【题意】

N1.1×10601

F a b[a, b]1
E a b[a, b]0
I a b[a, b]010110

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;
}