【hdu6186】CS Course(前缀后缀异或)

2017ACM/ICPC广西邀请赛 重现赛1005CS Course

题意

给一个数列a,每次询问去掉第p个的与和、或和,异或和。

题解

预处理前缀和、后缀和即可。
但是当时想都没想就写了个线段树。线段树就要注意不存在的区间,&操作返回1,其他返回0。

代码

const int N=201000;
int n,p,a[N];
int add(int a,int b,int t){
    if(t==0)
        return a&b;
    if(t==1)
        return a|b;
    return a^b;
}
struct SegTree{
    int s[N<<1];
    void build(int rt,int l,int r,int type){
        if(l==r){s[rt]=a[l];return;}
        build(rt<<1,l,l+r>>1,type);
        build(rt<<1|1,(l+r>>1)+1,r,type);
        s[rt]=add(s[rt<<1],s[rt<<1|1],type);
    }
    void Build(int n,int t){
        build(1,1,n,t);
    }
    int query(int rt,int l,int r,int L,int R,int type){
        if(l>R||r<L||L>R)return type==0?1:0;
        if(L<=l&&r<=R)
            return s[rt];
        int mid=l+r>>1;
        if(R<=mid)return query(rt<<1,l,mid,L,R,type);
        if(L>mid)return query(rt<<1|1,mid+1,r,L,R,type);
        return add(query(rt<<1,l,mid,L,mid,type),query(rt<<1|1,mid+1,r,mid+1,R,type),type);
    }
    int Query(int n,int s,int type){
        return add(query(1,1,n,1,s-1,type),query(1,1,n,s+1,n,type),type);
    }
}tree[3];
int main() {
    while(~scanf("%d%d",&n,&p)){
        rep(i,1,n+1)scanf("%d",a+i);
        rep(i,0,3)tree[i].Build(n, i);
        while(p--){
            int s;
            scanf("%d",&s);
            rep(i,0,3)printf("%d%c",tree[i].Query(n,s,i),i==2?'
':' ');
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/flipped/p/7469488.html