zoukankan      html  css  js  c++  java
  • Codeforces 1515 H. Phoenix and Bits 题解

    Codeforces 1515 H. Phoenix and Bits

    题意

    给出一个序列,有四种操作。

    1. 对于所有(l leq a_i leq r) ,使(a_i = a_i AND x)
    2. 对于所有(l leq a_i leq r) ,使(a_i = a_i OR x)
    3. 对于所有(l leq a_i leq r) ,使(a_i = a_i XOR x)
    4. 对于所有(l leq a_i leq r) ,不同的(a_i)的个数。

    考虑前三种操作,我们先将需要操作的子树(split)出来,操作完再(merge)回去。

    (a_i AND x)可以规约为(a_i XOR 2^{20}-1 , a_i OR x,a_i XOR 2^{20}-1)

    于是只需要考虑(2,3)操作,(3)操作可以通过打(tag)并交换子树实现,对于(2)操作,我们记录当前节点,有(1)的位置和有(0)的位置,(x)当前这位如果是(1),相当于把(0)节点全部合并到(1)节点上。如果既有(0)又有(1)就暴力递归(merge),否则就相当于交换子树,用(2)操作处理。

    由于每次暴力(merge),节点数就会减少(1),递归到这个节点的复杂度等于它的深度,是(O(logn))级别的, 节点数最多减少(O(nlogn))次,所以总复杂度是(O(nlog^2n))的。

    Code

    #include<bits/stdc++.h>
    #define ll long long
    #define N 200015
    #define rep(i,a,n) for (int i=a;i<=n;i++)
    #define per(i,a,n) for (int i=n;i>=a;i--)
    #define inf 0x3f3f3f3f
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define lowbit(i) ((i)&(-i))
    #define VI vector<int>
    #define all(x) x.begin(),x.end()
    #define SZ(x) ((int)x.size())
    using namespace std;
    int n,q,a[N];
    const int all = (1<<20)-1;
    int ls[N<<5],rs[N<<5],lz[N<<5],t0[N<<5],t1[N<<5],tr[N<<5],rt,tot;
    void pushup(int p){
    	tr[p] = tr[ls[p]]+tr[rs[p]];
    	t0[p] = t0[ls[p]]|t0[rs[p]];
    	t1[p] = t1[ls[p]]|t1[rs[p]];
    }
    void Xor(int p,int dep,int x){
    	if(!p) return;
    	if(x>>(dep-1)&1) swap(ls[p],rs[p]);
    	int v0 = (t1[p]&x)|(t0[p]&(~x)),v1 = (t0[p]&x)|(t1[p]&(~x));
    	t0[p] = v0; t1[p] = v1; lz[p] ^= x;
    }
    void pushdown(int p,int dep){
    	if(lz[p]){
    		Xor(ls[p],dep-1,lz[p]);
    		Xor(rs[p],dep-1,lz[p]);
    		lz[p] = 0;
    	}
    }
    void Split(int &u,int &v,int dep,int l,int r,int a,int b){
    	if(a <= l && r <= b){
    		v = u; u = 0;
    		return;
    	}
    	pushdown(u,dep);
    	v = ++tot;
    	int mid = (l+r)>>1;
    	if(a <= mid) Split(ls[u],ls[v],dep-1,l,mid,a,b);
    	if(b > mid) Split(rs[u],rs[v],dep-1,mid+1,r,a,b);
    	pushup(u); pushup(v);
    }
    void merge(int &u,int &v,int dep){
    	if(!u) return u = v,void();
    	if(!v || !dep) return;
    	pushdown(u,dep); pushdown(v,dep);
    	merge(ls[u],ls[v],dep-1); merge(rs[u],rs[v],dep-1);
    	pushup(u);
    }
    void ins(int &p,int x,int dep){
    	if(!p) p = ++tot;
    	if(!dep){
    		tr[p] = 1;
    		t0[p] = x^all;
    		t1[p] = x;
    		return;
    	}
    	if(x>>(dep-1)&1) ins(rs[p],x,dep-1);
    	else ins(ls[p],x,dep-1);
    	pushup(p);
    }
    void Or(int p,int dep,int x){
    	if(!p || !dep) return;
    	if(!(x&t0[p]&t1[p])){
    		Xor(p,dep,x&t0[p]);
    		return;
    	}
    	pushdown(p,dep);
    	if(x>>(dep-1)&1){
    		Xor(ls[p],dep-1,1<<(dep-1));
    		merge(rs[p],ls[p],dep-1);
    		ls[p] = 0;
    	}
    	Or(ls[p],dep-1,x);
    	Or(rs[p],dep-1,x);
    	pushup(p);
    }
    int query(int p,int dep,int l,int r,int x,int y){
    	if(x <= l && r <= y) return tr[p];
    	int mid = (l+r)>>1;
    	pushdown(p,dep);
    	int res = 0;
    	if(x <= mid) res += query(ls[p],dep-1,l,mid,x,y);
    	if(y > mid) res += query(rs[p],dep-1,mid+1,r,x,y);
    	return res;
    }
    int main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	scanf("%d%d",&n,&q);
    	rep(i,1,n){
    		int x; scanf("%d",&x);
    		ins(rt,x,20);
    	}
    	while(q--){
    		int typ,l,r,x;
    		scanf("%d%d%d",&typ,&l,&r);
    		if(typ <= 3){
    			int v;
    			scanf("%d",&x);
    			Split(rt,v,20,0,all,l,r);
    			if(typ == 1) Xor(v,20,all),Or(v,20,x^all),Xor(v,20,all);
    			if(typ == 2) Or(v,20,x);
    			if(typ == 3) Xor(v,20,x);
    			merge(rt,v,20);
    		}else{
    			printf("%d
    ",query(rt,20,0,all,l,r));
    		}
    	}
    	return 0;
    }
    
    !!!注意点!!!

    递归时记得(pushdown),有修改的操作回溯时要(pushup),注意(return)时的边界条件。

  • 相关阅读:
    Hadoop、spark
    Hadoop、spark
    Hadoop、spark
    Hadoop、spark
    SQL查询表中的用那些索引
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    【转】迷你区块链(mini blockchain in python)
    理解 Web 3
    【转】数字货币钱包:生态及技术
    【转】用 Witnet 协议使加密网络可以跨链访问
  • 原文地址:https://www.cnblogs.com/czdzx/p/14729386.html
Copyright © 2011-2022 走看看