Description
给定长度为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。
Solution
由于 m m m较大, n n n较小,所以对 Y Y Y建可持久化trie,每次询问就在trie上二分,不过稍微有点不同的是,通常是一个点在上面走,而现在是 n n n个点在上面走,其它的都差不多。
Code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=1010,Maxm=300010;
const int inf=2147483647;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,m,A[Maxn],B[Maxm],q;
int son[Maxm<<5][2],cnt[Maxm<<5],tot=0,root[Maxm];
void ins(int x)
{
root[x]=++tot;int last=root[x-1],cur=root[x];
for(int i=30;i>=0;i--)
{
int v=(1<<i)&B[x];if(v)v=1;
son[cur][v^1]=son[last][v^1];
son[cur][v]=++tot,cnt[tot]=cnt[son[last][v]]+1;
cur=son[cur][v],last=son[last][v];
}
}
int t1[Maxn],t2[Maxn];
int query(int L,int R,int l,int r,int k)//k小
{
int re=0;
for(int i=L;i<=R;i++)t2[i]=root[l-1],t1[i]=root[r];
for(int i=30;i>=0;i--)
{
int s=0;
for(int j=L;j<=R;j++)
{
int v=(1<<i)&A[j];if(v)v=1;
s+=cnt[son[t1[j]][v]]-cnt[son[t2[j]][v]];
}
if(s>=k)
{
for(int j=L;j<=R;j++)
{
int v=(1<<i)&A[j];if(v)v=1;
t1[j]=son[t1[j]][v],t2[j]=son[t2[j]][v];
}
}
else
{
k-=s;re|=(1<<i);
for(int j=L;j<=R;j++)
{
int v=(1<<i)&A[j];if(v)v=1;
t1[j]=son[t1[j]][v^1],t2[j]=son[t2[j]][v^1];
}
}
}
return re;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)A[i]=read();
root[0]=son[0][0]=son[0][1]=0;
for(int i=1;i<=m;i++)B[i]=read(),ins(i);
q=read();
while(q--)
{
int u=read(),d=read(),l=read(),r=read(),k=read();
int N=d-u+1,M=r-l+1;
printf("%d\n",query(u,d,l,r,N*M-k+1));
}
}