4103: [Thu Summer Camp 2015]异或运算

来源:互联网 发布:平平无奇 古天乐 知乎 编辑:程序博客网 时间:2024/06/05 01:15

题面:给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi xor  yj,每次询问给定矩形区域i∈[u,d],j∈[l,r],找出第k大的Aij。(n<=1000,m<=300000)

思路:因为n比较小,所以维护第二维,然后暴力询问第一维。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1010,maxm=300010,maxt=10000010;int n,m,x[maxn],y[maxm],q,a,b,c,d,k;struct Tree{struct node{int size,son[2];}t[maxt];int tot,root[maxm],a[maxm],t1[maxn],t2[maxn];int newnode(){return ++tot;}void insert(int id,int val){root[id]=newnode();t[root[id]].size=t[root[id-1]].size+1;int now=root[id],pre=root[id-1];for (int j=31,v;j>=0;j--){v=(val>>j)&1;t[now].son[v]=newnode();t[t[now].son[v]].size=t[t[pre].son[v]].size+1;t[now].son[v^1]=t[pre].son[v^1];now=t[now].son[v],pre=t[pre].son[v];}}void query(int u,int d,int l,int r,int rank){for (int i=u;i<=d;i++) t1[i]=root[l-1],t2[i]=root[r];int res=0;for (int k=31;k>=0;k--){int sum=0;for (int i=u;i<=d;i++){int v=(x[i]>>k)&1;sum+=t[t[t2[i]].son[v^1]].size-t[t[t1[i]].son[v^1]].size;}if (rank<=sum){for (int i=u;i<=d;i++){int v=(x[i]>>k)&1;t1[i]=t[t1[i]].son[v^1],t2[i]=t[t2[i]].son[v^1];}res|=(1<<k);}else{for (int i=u;i<=d;i++){int v=(x[i]>>k)&1;t1[i]=t[t1[i]].son[v],t2[i]=t[t2[i]].son[v];}rank-=sum;}}printf("%d\n",res);}}Trie;int main(){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) scanf("%d",&x[i]);for (int i=1;i<=m;i++) scanf("%d",&y[i]);for (int i=1;i<=m;i++) Trie.insert(i,y[i]);for (scanf("%d",&q);q;q--) scanf("%d%d%d%d%d",&a,&b,&c,&d,&k),Trie.query(a,b,c,d,k);return 0;}


0 0
原创粉丝点击