第一次打可持久化trie树。。不过貌似不是太难打?
M很大 对M个数来建可持久化trie树 N较小 在询问的时候一起搞就好
不难得出复杂度
O(m∗32+n∗q∗32)
异或这种东西 不难就能想到用trie树 然后统计一下数量 搞一下 求第K大
比如让它尽量大的话 这一位是0就走去1 是1的话就反之
自认为代码还是挺好看的~(为什么我又觉得他有点慢)
#include<bits/stdc++.h>
using namespace std;
const int N=1002,M=300002,D=30;
inline int read(){
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
return x*f;
}
int a[N],rt[M],tot,lc[M*32],rc[M*32],c[M*32];
void add(int id,int x){
rt[id]=++tot; int y=rt[id-1],nw=tot;
for(int i=D;~i;i--){
int u=x>>i; x&=(1<<i)-1;
if(u){
rc[nw]=++tot,c[tot]=c[rc[y]]+1;
lc[nw]=lc[y],nw=tot,y=rc[y];
}
else{
lc[nw]=++tot,c[tot]=c[lc[y]]+1;
rc[nw]=rc[y],nw=tot,y=lc[y];
}
}
}
int nl[N],nr[N],L,R,l,r,k;
void query(){
int ret=0,i;
for(i=L;i<=R;i++)nl[i]=rt[l-1],nr[i]=rt[r];
for(i=D;~i;i--){
int x=0;
for(int j=L;j<=R;j++){
int u=(a[j]>>i)&1;
if(u)x+=c[lc[nr[j]]]-c[lc[nl[j]]];
else x+=c[rc[nr[j]]]-c[rc[nl[j]]];
}
if(x>=k){
for(int j=L;j<=R;j++){
int u=(a[j]>>i)&1;
if(u)nr[j]=lc[nr[j]],nl[j]=lc[nl[j]];
else nr[j]=rc[nr[j]],nl[j]=rc[nl[j]];
}
ret|=(1<<i);
}
else{
k-=x;
for(int j=L;j<=R;j++){
int u=(a[j]>>i)&1;
if(u)nr[j]=rc[nr[j]],nl[j]=rc[nl[j]];
else nr[j]=lc[nr[j]],nl[j]=lc[nl[j]];
}
}
}
printf("%d\n",ret);
}
int main()
{
int n=read(),m=read(),i,x;
for(i=1;i<=n;i++)a[i]=read();
for(i=1;i<=m;i++){
x=read(); add(i,x);
}
int q=read();
while(q--){
L=read(),R=read(),l=read(),r=read(),k=read();
query();
}
return 0;
}