• bzoj3261: 最大异或和


    题面:给定一个非负整数序列 {a},初始长度为 N。       
    有   M个操作,有以下两种操作类型:
     1 、A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1。
    2 、Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:

     a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少。  

    思路:因为是xor,所以用可持久化trie。设前i项的异或和为sum[i],那么询问的答案就是max(sum[n]^x^sum[i]),因为sum[n]^x是常数,所以我们只要维护sum[i]

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=60010,maxt=maxn*32;
    int n,a[maxn],prec[maxn],suc[maxn],ans=0;
    
    struct node{int size,c[2];};
    struct Trie{
    	node t[maxt];int root[maxn],tot;
    	void insert(int id,int val){
    		root[id]=++tot,t[root[id]].size+=t[root[id-1]].size+1;
    		for (int j=31,v,now=root[id],pre=root[id-1];j>=0;j--){
    			v=(val>>j)&1,t[now].c[v]=++tot;
    			t[t[now].c[v]].size=t[t[pre].c[v]].size+1;
    			t[now].c[v^1]=t[pre].c[v^1];
    			now=t[now].c[v],pre=t[pre].c[v];
    		}
    	}
    	int query(int l,int r,int val){
    		int a=root[l-1],b=root[r],ans=0;
    		for (int j=31;j>=0;j--){
    			int v=(val>>j)&1;
    			if (t[t[b].c[v^1]].size-t[t[a].c[v^1]].size) ans|=(1<<j),a=t[a].c[v^1],b=t[b].c[v^1];
    			else a=t[a].c[v],b=t[b].c[v];
    		}
    		return ans;
    	}
    }T;
    
    int main(){
    	scanf("%d",&n);T.insert(1,0);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]),T.insert(i,a[i]);
    	for (int i=1,cnt,x;i<=n;i++){
    		for (cnt=0,x=i-1;x&&cnt!=2;) if (a[x--]>a[i]) cnt++;prec[i]=x+1;
    		for (cnt=0,x=i+1;x!=n+1&&cnt!=2;) if (a[x++]>a[i]) cnt++;suc[i]=x-1;
    	}
    	for (int i=1;i<=n;i++) ans=max(ans,T.query(prec[i],suc[i],a[i]));
    	printf("%d
    ",ans);
    	return 0;
    }

    就可以了。

  • 相关阅读:
    面试题 31: 求子数组的最大和
    [面试] 结构体占用空间的问题,内存对齐~! 真的懂了,cpu取加快速度,省空间来考虑。
    [计算机] 32768~32767 计算机中的 1 表示
    C#跨线程调用窗体控件
    合并字节数组
    将汉字转化为2位大写的16进制Unicode
    关公与子龙两大杀手
    早年的J2EE笔记
    给小组新成员的一份信
    c++虚函数详解
  • 原文地址:https://www.cnblogs.com/thythy/p/5493591.html
Copyright © 2020-2023  润新知