zoukankan      html  css  js  c++  java
  • CodeForces

    题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 

    做法一:
    对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线性基。

    用线段树去维护区间合并

    #include <bits/stdc++.h>
     
    using namespace std;
    const int maxn = 1e5;
    struct node {
        int bas[30],lazy,st;
        void init() {
            memset(bas,0,sizeof(bas));
            lazy = 0;st = 0;
        }
        int Count() {
            int ans = 0;
            for(int i = 0;i<=29;i++) {
                if(bas[i]) ans++;
            }
            return ans;
        }
        void add(int x) {
            for(int i = 29;i>=0;i--) {
                if((x>>i)&1){
                    if(bas[i])x^=bas[i];
                    else {
                        bas[i] = x;
                        break;
                    }
                }
            }
        }
        node operator + (const node &a) const{
            node ans;  ans.init();
            for(int i = 0;i<=29;i++) {
                ans.add(bas[i]);
                ans.add(a.bas[i]);
            }
            ans.add(st^a.st);
            ans.st = a.st;
            return ans;
        }
    }tr[8*maxn],ans;
    int n,q;
    void pushdown(int st) {
        if(tr[st].lazy) {
            tr[st<<1].lazy ^= tr[st].lazy;
            tr[st<<1].st ^= tr[st].lazy;
            tr[st<<1|1].lazy ^= tr[st].lazy;
            tr[st<<1|1].st ^= tr[st].lazy;
            tr[st].lazy = 0;
        }
    }
    void build(int l,int r,int st) {
        tr[st].init();
        if(l == r) {
            scanf("%d",&tr[st].st);
            return ;
        }
        int mid = (l+r)>>1;
        build(l,mid,st<<1);
        build(mid+1,r,st<<1|1);
        tr[st] = tr[st<<1] + tr[st<<1|1];
    }
    void update(int l,int r,int st,int L,int R,int d) {
        if(l>=L && r<=R) {
            tr[st].lazy ^= d;
            tr[st].st ^= d;
            return ;
        }
        pushdown(st);
        int mid = (l+r) >>1;
        if(L<=mid) update(l,mid,st<<1,L,R,d);
        if(R> mid) update(mid+1,r,st<<1|1,L,R,d);
        tr[st] = tr[st<<1] + tr[st<<1|1];
    }
    void Query(int l,int r,int st,int L,int R) {
        if(l >= L && r <= R) {
            ans = ans + tr[st];
            return ;
        }
        pushdown(st);
        int mid = (l+r) >>1;
        if(L<=mid) Query(l,mid,st<<1,L,R);
        if(R>mid)  Query(mid+1,r,st<<1|1,L,R);
        tr[st] = tr[st<<1] + tr[st<<1|1];
    }
    int main() {
        int op,l,r,d;
        scanf("%d %d",&n,&q);
        build(1,n,1);
        while(q--) {
            scanf("%d %d %d",&op,&l,&r);
            if(op == 1) {
                scanf("%d",&d);
                update(1,n,1,l,r,d);
            }
            else {
                ans.init();
                Query(1,n,1,l,r);
                printf("%d
    ",1<<ans.Count());
            }
        }
        return 0;
    }
    View Code

    做法二:

    对原序列a进行差分,使得b[i] = a[i] ^ a[i+1],那么al,al+1,al+2,ar可以构成的一个异或和,在al,bl,bl+1,bl+2,br-1中肯定也可以被构造出来,因此二者是等价的。

    对于a序列的区间[l,r]的更新实际上b序列上只有bl-1和br被影响,中间的数由于是两两所以抵消掉了。

    所以现在就变成了单点更新线段树维护区间线性基,然后再用一个树状数组维护l位置被修改的值,这也用到了差分,这里的作用是要求a[l]的值。

    #include <bits/stdc++.h>
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    using namespace std;
    const int mx = 2e5 + 10;
    int n,m,a[mx],b[mx];
    int pre[mx],mv;
    struct node{
        int gao[31];
        void add(int x){
            for(int i=29;i>=0;i--){
                if(x&(1<<i)){
                    if(!gao[i]){
                        gao[i] = x;
                        break;
                    }else x ^= gao[i];
                }
            }
        }
        node operator + (node A)const
        {
            node ret = A;
            for(int i=29;i>=0;i--)
            if(gao[i]) ret.add(gao[i]);
            return ret;
        }
    }s[mx<<2];
    void add(int x,int v){
        while(x<=n){
            pre[x] ^= v;
            x += x&(-x);
        }
    }
    int getpre(int x){
        int ans = 0;
        while(x){
            ans ^= pre[x];
            x -= x&(-x);
        }
        return ans;
    }
    void build(int l,int r,int rt)
    {
        if(l==r){
            b[l] = a[l]^a[l+1];
            for(int i=29;i>=0;i--)
            if((1<<i)&b[l]){
                s[rt].gao[i] = b[l];
                break;
            }
            return ;
        } 
        int mid = (l+r)>>1;
        build(lson);build(rson);
        s[rt] = s[rt<<1] + s[rt<<1|1];
    }
    void update(int l,int r,int rt,int M)
    {
        if(l==r){
            b[l] ^= mv;
            memset(s[rt].gao,0,sizeof(s[rt].gao));
            for(int i=29;i>=0;i--)
            if((1<<i)&b[l]){
                s[rt].gao[i] = b[l];
                break;
            }
            return ;
        }
        int mid = (l+r)>>1;
        if(M<=mid) update(lson,M);
        else update(rson,M);
        s[rt] = s[rt<<1] + s[rt<<1|1];
    } 
    node query(int l,int r,int rt,int L,int R)
    {
        if(L<=l&&r<=R) return s[rt];
        int mid = (l+r)>>1;
        if(L<=mid&&R>mid) return query(lson,L,R) + query(rson,L,R);
        if(L<=mid) return query(lson,L,R);
        return query(rson,L,R);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        if(n>1) build(1,n-1,1);
        int o,l,r;
        while(m--){
            scanf("%d%d%d",&o,&l,&r);
            if(o==1){
                scanf("%d",&mv);
                add(l,mv);add(r+1,mv);
                if(l>1) update(1,n-1,1,l-1);
                if(r<n) update(1,n-1,1,r);
            }else{
                int v = a[l]^getpre(l);
                if(n==1||l==r) printf("%d
    ",v?2:1);
                else{
                    node ans = query(1,n-1,1,l,r-1);
                    ans.add(v);
                    int ret = 0;
                    for(int i=29;i>=0;i--)
                    if(ans.gao[i]) ret++;
                    printf("%d
    ",1<<ret);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    模拟Session原理
    练手项目通讯录
    Win 8前台开发小体会
    WP自定义控件
    任务锁和自定义控件制作
    window文件复制到linux系统下
    Linux:Ubuntu配置jdk环境变量
    ubuntu 20 安装完成,配置ip信息
    Unity骨骼优化(转)
    利用栈实现简单计算器
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/11350154.html
Copyright © 2011-2022 走看看