【BZOJ 4103】[Thu Summer Camp 2015]异或运算 可持久化trie树

来源:互联网 发布:java项目开发全程过程 编辑:程序博客网 时间:2024/06/08 00:29

矩阵什么的不用管,就是a给一个区间,b给一个区间两两异或第k大,发现b很大a很小,就给b建一个可持久化trie树,顺便记下size以便于查询第k大。

对于每一次的询问,外层枚举位数,内层枚举A的每一个数,用结构体存下每一个A中的数对应的B的可持久化trie树的当前节点,然后分别就像查询一个数一样树上二分就好了。

#include<cstdio>#include<cstring>#include<iostream>#define maxm 300021#define ls(u) ch[u][0]#define rs(u) ch[u][1]using namespace std;int n,m,a[1021],tot,rt[maxm],ch[maxm*40][2];int size[maxm*40];struct node{int x,y,val;}q[maxm];void insert(int x,int& y,int val){y=++tot;int root=y;size[y]=size[x]+1;for(int c,i=31;i>=0;i--){c=(val>>i)&1;ch[root][!c]=ch[x][!c];root=ch[root][c]=++tot;x=ch[x][c];size[root]=size[x]+1;}}int query(int cnt,int k){int sz=0,ans=0;for(int i=31;i>=0;i--){sz=0;for(int c,j=1;j<=cnt;j++){c=(q[j].val>>i)&1;sz+=size[ch[q[j].y][!c]]-size[ch[q[j].x][!c]];}if(sz>=k){ans=ans<<1|1;for(int j=1,c;j<=cnt;j++){c=(q[j].val>>i)&1;q[j].x=ch[q[j].x][!c],q[j].y=ch[q[j].y][!c];}}else{k-=sz;ans=ans<<1;for(int j=1,c;j<=cnt;j++){c=(q[j].val>>i)&1;q[j].x=ch[q[j].x][c],q[j].y=ch[q[j].y][c];}}}return ans;}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",a+i);for(int x,i=1;i<=m;i++){scanf("%d",&x);insert(rt[i-1],rt[i],x);}int Q;int u,d,l,r,k,cnt;scanf("%d",&Q);while(Q--){cnt=0;scanf("%d%d%d%d%d",&u,&d,&l,&r,&k);for(int i=u;i<=d;i++)q[++cnt]=(node){rt[l-1],rt[r],a[i]};printf("%d\n",query(cnt,k));}return 0;}


0 0
原创粉丝点击