[BZOJ4103] 异或运算
抱佛脚...
首先想到查找第K大的异或值可以按为确定,方法类似平衡树查第K大
然后,就跑到前缀和上去死磕了...
然而明明一颗可持久化trie树就可以解决的...
然后n*p*32^2过了以后表示老夫怎么这么慢阿,,,于是发现别人是n*p*32的,每次记下来就好,不用再跑一遍的...
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mp make_pair 4 #define fir first 5 #define sec second 6 #define maxn 1005 7 #define maxm 300005 8 #define maxnd 10000005 9 #define maxl 32 10 int A[maxn],B[maxm]; 11 int nd,root[maxm],trie[maxnd][2],mrk[maxnd]; 12 pair<int,int>at[maxn]; 13 int read(){ 14 int tmp=0; char ch=0; 15 while(ch<'0'||ch>'9')ch=getchar(); 16 while(ch>='0'&&ch<='9')tmp=tmp*10+ch-'0',ch=getchar(); 17 return tmp; 18 } 19 void insert(int pos){ 20 int x=++nd,y=root[pos-1]; 21 root[pos]=x; 22 for(int i=maxl-1;i>=0;i--){ 23 int val=(B[pos]>>i)&1; 24 trie[x][val^1]=trie[y][val^1]; 25 mrk[x]=mrk[y]+1; 26 trie[x][val]=++nd; 27 x=trie[x][val],y=trie[y][val]; 28 } 29 mrk[x]=mrk[y]+1; 30 } 31 int solve(int u,int d,int l,int r,int k){ 32 int ans=0; 33 for(int j=u;j<=d;j++) 34 at[j]=mp(root[r],root[l-1]); 35 for(int i=maxl-1;i>=0;i--){ 36 int cnt=0; 37 for(int j=u;j<=d;j++){ 38 int val=(A[j]>>i)&1; 39 cnt+=mrk[trie[at[j].fir][val^1]]-mrk[trie[at[j].sec][val^1]]; 40 } 41 if(cnt>=k){ 42 ans+=1<<i; 43 for(int j=u;j<=d;j++){ 44 int val=(A[j]>>i)&1; 45 at[j]=mp(trie[at[j].fir][val^1],trie[at[j].sec][val^1]); 46 } 47 } 48 else{ 49 k-=cnt; 50 for(int j=u;j<=d;j++){ 51 int val=(A[j]>>i)&1; 52 at[j]=mp(trie[at[j].fir][val],trie[at[j].sec][val]); 53 } 54 } 55 } 56 return ans; 57 } 58 int main(){ 59 int n,m,q,u,d,l,r,k; 60 n=read(),m=read(); 61 for(int i=1;i<=n;i++)A[i]=read(); 62 for(int i=1;i<=m;i++){ 63 B[i]=read(); 64 insert(i); 65 } 66 q=read(); 67 for(int i=1;i<=q;i++){ 68 u=read(),d=read(),l=read(),r=read(),k=read(); 69 printf("%d\n",solve(u,d,l,r,k)); 70 } 71 return 0; 72 }