您的位置:首页 > 其它

[BZOJ4103] 异或运算

2016-05-29 10:16 302 查看
抱佛脚...

首先想到查找第K大的异或值可以按为确定,方法类似平衡树查第K大

然后,就跑到前缀和上去死磕了...

然而明明一颗可持久化trie树就可以解决的...

然后n*p*32^2过了以后表示老夫怎么这么慢阿,,,于是发现别人是n*p*32的,每次记下来就好,不用再跑一遍的...

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define fir first
#define sec second
#define maxn 1005
#define maxm 300005
#define maxnd 10000005
#define maxl 32
int A[maxn],B[maxm];
int nd,root[maxm],trie[maxnd][2],mrk[maxnd];
pair<int,int>at[maxn];
int read(){
int tmp=0; char ch=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')tmp=tmp*10+ch-'0',ch=getchar();
return tmp;
}
void insert(int pos){
int x=++nd,y=root[pos-1];
root[pos]=x;
for(int i=maxl-1;i>=0;i--){
int val=(B[pos]>>i)&1;
trie[x][val^1]=trie[y][val^1];
mrk[x]=mrk[y]+1;
trie[x][val]=++nd;
x=trie[x][val],y=trie[y][val];
}
mrk[x]=mrk[y]+1;
}
int solve(int u,int d,int l,int r,int k){
int ans=0;
for(int j=u;j<=d;j++)
at[j]=mp(root[r],root[l-1]);
for(int i=maxl-1;i>=0;i--){
int cnt=0;
for(int j=u;j<=d;j++){
int val=(A[j]>>i)&1;
cnt+=mrk[trie[at[j].fir][val^1]]-mrk[trie[at[j].sec][val^1]];
}
if(cnt>=k){
ans+=1<<i;
for(int j=u;j<=d;j++){
int val=(A[j]>>i)&1;
at[j]=mp(trie[at[j].fir][val^1],trie[at[j].sec][val^1]);
}
}
else{
k-=cnt;
for(int j=u;j<=d;j++){
int val=(A[j]>>i)&1;
at[j]=mp(trie[at[j].fir][val],trie[at[j].sec][val]);
}
}
}
return ans;
}
int main(){
int n,m,q,u,d,l,r,k;
n=read(),m=read();
for(int i=1;i<=n;i++)A[i]=read();
for(int i=1;i<=m;i++){
B[i]=read();
insert(i);
}
q=read();
for(int i=1;i<=q;i++){
u=read(),d=read(),l=read(),r=read(),k=read();
printf("%d\n",solve(u,d,l,r,k));
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: