2018.08.18 线段树(线段树)

线段树
描述
请你维护一个线段树
支持一下操作
A x l r 区间 and x
O x l r区间 Or x
X x l r 区间 Xor x
S l r 区间求和
输入
一个数 T表示数据组数 一个数n表示初始序列长 m表示查询 随后n个整数 接下来m次询问 如上
输出
所以S次询问的答案
样例输入
1
4 1
1 2 4 7
S 0 2
样例输出
7
提示
为防止min-max剪枝 n=1e6 m=1e5 Ai<15 T<=3

线段树经典题。
第一眼还以为是与或的翻版,仔细看了看这东西不能用类似的做法跑过去233。。。
然后就惊奇的发现了Ai<15这个条件,这暗示了我把每个数拆成4个二进制位,这样三个修改相当于区间覆盖跟区间01序列翻转了,这显然是可做的啊。
代码:

#include<bits/stdc++.h>
#define N 1000005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p][op].l+T[p][op].r>>1)
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans; 
}
int T_T,n,m,a[N];
struct Node{int l,r,sum,tag;}T[N<<2][4];
inline void pushup(int p,int op){T[p][op].sum=T[lc][op].sum+T[rc][op].sum;}
inline void pushnow(int p,int op,int k){
    if(k<2)T[p][op].tag=k,T[p][op].sum=(T[p][op].r-T[p][op].l+1)*k;
    else{
        if(T[p][op].tag<2)T[p][op].tag^=1,T[p][op].sum=(T[p][op].r-T[p][op].l+1)*T[p][op].tag;
        else if(T[p][op].tag==2)T[p][op].tag=3,T[p][op].sum=T[p][op].r-T[p][op].l+1-T[p][op].sum;
        else T[p][op].tag=2,T[p][op].sum=T[p][op].r-T[p][op].l+1-T[p][op].sum;
    }
}
inline void pushdown(int p,int op){if(T[p][op].tag!=3)pushnow(lc,op,T[p][op].tag),pushnow(rc,op,T[p][op].tag),T[p][op].tag=3;}
inline void build(int p,int l,int r,int op){
    T[p][op].l=l,T[p][op].r=r,T[p][op].tag=3;
    if(l==r){T[p][op].sum=(a[l]&(1<<op))>>op;return;}
    build(lc,l,mid,op),build(rc,mid+1,r,op),pushup(p,op);
}
inline void update(int p,int ql,int qr,int op,int k){
    if(ql>T[p][op].r||qr<T[p][op].l)return;
    if(ql<=T[p][op].l&&T[p][op].r<=qr)return pushnow(p,op,k);
    pushdown(p,op);
    if(qr<=mid)update(lc,ql,qr,op,k);
    else if(ql>mid)update(rc,ql,qr,op,k);
    else update(lc,ql,mid,op,k),update(rc,mid+1,qr,op,k);
    pushup(p,op); 
}
inline int query(int p,int ql,int qr,int op){
    if(ql>T[p][op].r||qr<T[p][op].l)return 0;
    if(ql<=T[p][op].l&&T[p][op].r<=qr)return T[p][op].sum;
    pushdown(p,op);
    if(qr<=mid)return query(lc,ql,qr,op);
    if(ql>mid)return query(rc,ql,qr,op);
    return query(lc,ql,mid,op)+query(rc,mid+1,qr,op); 
}
int main(){
    T_T=read();
    while(T_T--){
        n=read(),m=read();
        for(int i=1;i<=n;++i)a[i]=read();
        for(int i=0;i<4;++i)build(1,1,n,i);
        while(m--){
            char s[4];
            scanf("%s",s);
            if(s[0]=='S'){
                int l=read()+1,r=read()+1;
                int ans=0;
                for(int i=0;i<4;++i)ans+=query(1,l,r,i)<<i;
                printf("%d\n",ans);
            }
            if(s[0]=='A'){
                int x=read(),l=read()+1,r=read()+1;
                for(int i=0;i<4;++i){
                    if((x&(1<<i)))continue;
                    update(1,l,r,i,0);
                }
            }
            if(s[0]=='O'){
                int x=read(),l=read()+1,r=read()+1;
                for(int i=0;i<4;++i)if((x&(1<<i)))update(1,l,r,i,1);
            }
            if(s[0]=='X'){
                int x=read(),l=read()+1,r=read()+1;
                for(int i=0;i<4;++i)if((x&(1<<i)))update(1,l,r,i,2);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/81809875