现在再来切是不是有点晚QAQ
题目大意是给定两个正整数序列。规定矩阵(异或运算),每个询问求某个子矩阵内第k大的值。其中。
注意到N和Q比较小,所以就是把序列B建成可持久Trie,然后同时跑A中的若干个数。。。
如果想不清楚可以先考虑当N=1,也就是A是一个数的情况,然后再考虑如何合并。
/**************************************************************
Problem: 4103
User: cqyzhb
Language: C++
Result: Accepted
Time:5364 ms
Memory:126804 kb
****************************************************************/
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define MAXN 300005
void _read(int &x)
{
x=0; char ch=getchar(); bool flag=false;
while(ch<'0' || ch>'9'){if(ch=='-')flag=true; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} if(flag)x=-x; return ;
}
int N,M,A[1005],B[MAXN],sum[32][1005],np;
int chi[MAXN*35][2],sz[MAXN*35],rt[MAXN];
void Insert(int anc,int &rt,int x)
{
rt=++np; int now=np; sz[now]=sz[anc]+1;;
for(int i=30;i>=0;i--)
{
if((1<<i)&x)
{
chi[now][0]=chi[anc][0]; chi[now][1]=++np; sz[chi[now][1]]=sz[chi[anc][1]]+1;
now=chi[now][1]; anc=chi[anc][1];
}
else
{
chi[now][1]=chi[anc][1]; chi[now][0]=++np; sz[chi[now][0]]=sz[chi[anc][0]]+1;
now=chi[now][0]; anc=chi[anc][0];
}
}
return ;
}
void Init()
{
_read(N);_read(M);
for(int i=1;i<=N;i++)_read(A[i]); for(int i=1;i<=M;i++)_read(B[i]);
rt[0]=0; np=0; sz[0]=0;
for(int i=1;i<=M;i++)Insert(rt[i-1],rt[i],B[i]);
for(int i=0;i<=30;i++)
{
sum[i][0]=0;
for(int j=1;j<=N;j++)
{
if(A[j]&(1<<i))sum[i][j]=sum[i][j-1]+1;
else sum[i][j]=sum[i][j-1];
}
}
return ;
}
int tmp[1005][2];
void query(int anc,int now,int L,int R,int k)
{
int ct=0,t=0,ans=0;
for(int i=L;i<=R;i++)
{
tmp[i][0]=anc; tmp[i][1]=now;
}
for(int i=30;i>=0;i--)
{
t=0;
for(int j=L;j<=R;j++)
{
if(A[j]&(1<<i))
{
t+=sz[chi[tmp[j][1]][1]]-sz[chi[tmp[j][0]][1]];
}
else
{
t+=sz[chi[tmp[j][1]][0]]-sz[chi[tmp[j][0]][0]];
}
}
if(ct+t>=k) // 答案的这一位是0
{
for(int j=L;j<=R;j++)
{
if(A[j]&(1<<i)) // 向1那边走
{
tmp[j][0]=chi[tmp[j][0]][1];tmp[j][1]=chi[tmp[j][1]][1];
}
else
{
tmp[j][0]=chi[tmp[j][0]][0];tmp[j][1]=chi[tmp[j][1]][0];
}
}
}
else // 1
{
ans+=(1<<i); ct+=t;
for(int j=L;j<=R;j++)
{
if(A[j]&(1<<i)) // 向0那边走
{
tmp[j][0]=chi[tmp[j][0]][0];tmp[j][1]=chi[tmp[j][1]][0];
}
else
{
tmp[j][0]=chi[tmp[j][0]][1];tmp[j][1]=chi[tmp[j][1]][1];
}
}
}
}
printf("%d\n",ans);
return ;
}
void work()
{
int u,d,l,r,k,Q;
_read(Q);
for(int i=1;i<=Q;i++)
{
_read(u); _read(d); _read(l); _read(r); _read(k); k=(d-u+1)*(r-l+1)+1-k;
query(rt[l-1],rt[r],u,d,k);
}
return ;
}
int main()
{
// freopen("in.txt","r",stdin);
Init();
work();
return 0;
}