zoukankan      html  css  js  c++  java
  • 【bzoj4571】美味

    Portal -->bzoj4571

    Solution

      emmm持续智力康复。。

      虽然说因为统计的是加上(x)的跟(b)异或的最大值所以可持久化trie用不了了

    ​  但是按位贪心的思想还是非常ok的

      然后又因为权值范围比较小,那就权值线段树然后可持久化一下,对于一个查询(b),我们从高位到低位枚举每一位,对于当前枚举到的第(j)位,先确定一个范围,这个范围内的任意一个数(i)加上(x)后都满足(i)^(b)的结果的第(j)位为1,然后我们在这个范围内的主席树上查一下有没有在这个区间内的数,有的话就说明这位可以满足异或后为(1),搞到答案里面去,否则就不能为(1),不管,然后接着枚举下一位,总的复杂度(O(nlog^2n))

      (其实就是。。把按位贪心的过程从trie上面搬到了主席树上。。)

    ​   

    ​  代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=2*(1e5)+10,SEG=N*20,MX=N,TOP=20;
    int a[N];
    int n,m,mx,L,R;
    namespace Seg{/*{{{*/
    	int ch[SEG][2],sum[SEG],rt[N];
    	int n,tot;
    	void init(int _n){n=_n; tot=0;}
    	int newnode(int pre){
    		ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1]; sum[tot]=sum[pre];
    		return tot;
    	}
    	void _insert(int pre,int &x,int d,int lx,int rx){
    		x=newnode(pre);
    		++sum[x];
    		if (lx==rx) return;
    		int mid=lx+rx>>1;
    		if (d<=mid) _insert(ch[pre][0],ch[x][0],d,lx,mid);
    		else _insert(ch[pre][1],ch[x][1],d,mid+1,rx);
    	}
    	void insert(int pre,int x,int d){_insert(rt[pre],rt[x],d,1,n);}
    	bool _query(int L,int R,int l,int r,int lx,int rx){
    		if (!R) return 0;
    		if (l<=lx&&rx<=r) return (sum[R]-sum[L])>0;
    		int mid=lx+rx>>1,ret=0;
    		if (l<=mid) ret|=_query(ch[L][0],ch[R][0],l,r,lx,mid);
    		if (r>mid) ret|=_query(ch[L][1],ch[R][1],l,r,mid+1,rx);
    		return ret;
    	}
    	bool query(int tL,int tR,int l,int r){return _query(rt[tL-1],rt[tR],l,r,1,n);}
    }/*}}}*/
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int b,x,l,r,tmp;
    	scanf("%d%d",&n,&m);
    	Seg::init(MX);
    	for (int i=1;i<=n;++i){
    		scanf("%d",a+i);
    		Seg::insert(i-1,i,a[i]);
    	}
    	for (int i=1;i<=m;++i){
    		scanf("%d%d%d%d",&b,&x,&l,&r);
    		tmp=0;
    		for (int j=TOP;j>=0;--j){
    			if (b>>j&1){
    				L=max(0,tmp-x); R=(tmp|((1<<j)-1))-x;
    				if (R<0||!Seg::query(l,r,L,R)) tmp^=(1<<j);
    			}
    			else{
    				L=max(0,(tmp^(1<<j))-x); R=((tmp^(1<<j))|((1<<j)-1))-x;
    				if (R<0||!Seg::query(l,r,L,R)) continue;
    				else tmp^=(1<<j);
    			}
    		}
    		printf("%d
    ",tmp^b);
    	}
    }
    
  • 相关阅读:
    jscript 处理文件
    网页右键菜单制作小demo
    精通正则表达式(元字符)
    精通正则表达式(正则引擎)
    js动态加载脚本
    精通正则表达式(JavaScript)
    Flex帮助文档制作(ASDoc——html篇)
    Flex帮助文档制作(FAR——chm篇)
    最基础的发布服务小demo
    Flex帮助文档制作(ASDoc——注释篇1)
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9395931.html
Copyright © 2011-2022 走看看