BZOJ 4103 [Thusc 2015]异或运算 (可持久化01Trie+二分)
题目大意:给你一个长方形矩阵,位置$i,j$上的数是$a_{i}\;xor\;b_{j}$,求某个子矩阵内第$K$大的值
最先想的是二分答案然后验证,然而是$O(qnlogmloga_{i})$,不出意外会被卡..看完题解才恍然大悟
$01Trie$是具有二分性质的!因为每个节点最多有2个儿子!
先对$b$序列建可持久化$01Trie$,记录一个$sum$表示当前节点的子树内有多少个数
对于每次询问,因为$n$很小,暴力枚举$a$进行统计,记录每个a当前在01Trie的位置
接下来就是在$01Trie$上二分了
按位从高到低枚举,统计一共有多少个数这一位是1,即每个a所在$01Trie$位置 和这一位异或值为1 的子树内,记为$tot$
如果$tot>k$,说明这一位不是1,每个$a$分别向异或值是0的地方走,然后$K-=tot$,去掉这一位填1的贡献
反之每个$a$往异或值为1的地方走
最后输出答案即可
#include <set> #include <queue> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #define N1 301000 #define N2 10201000 #define MM 100 #define ll long long #define dd double #define uint unsigned int #define mod 1000000007 #define idx(X) (X-'a') #define it multiset<node>::iterator using namespace std; int gint() { int ret=0,fh=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} return ret*fh; } uint bin[35]; int n,m; uint a[N1],b[N1],pa[N1]; int px[N1],py[N1]; struct Trie{ int ch[N2][2],num[N2],root[N1],tot; int sum[N2],stk[N2],tp; void init() { root[0]=tot=1;int x=1; for(int i=30;i>=0;i--){ ch[x][0]=++tot; x=ch[x][0],num[x]=1; } } void insert(int s,int rt1,int rt2,int w) { int x,y,p; y=root[rt1]; x=root[rt2]=++tot; for(int i=31;i>=0;i--){ p=(s&bin[i])?1:0; ch[x][p]=++tot; ch[x][p^1]=ch[y][p^1]; num[ch[x][p]]=num[ch[y][p]]+w; sum[ch[x][p]]=sum[ch[y][p]]; x=ch[x][p],y=ch[y][p]; stk[++tp]=x; } sum[x]++,stk[tp--]=0; while(tp){ x=stk[tp--]; sum[x]=sum[ch[x][0]]+sum[ch[x][1]]; } } uint query(int L,int R,int l,int r,int K) { int x,y,p;uint ans=0; y=l<0?0:root[l],x=root[r]; int s[2],tot; for(int j=L;j<=R;j++) px[j]=x,py[j]=y; for(int i=31;i>=0;i--) { s[0]=0,s[1]=0,tot=0; for(int j=L;j<=R;j++){ p=(a[j]&bin[i])?1:0,s[p]++; tot+=sum[ch[px[j]][p^1]]-sum[ch[py[j]][p^1]]; } if(K>tot){ K-=tot; for(int j=L;j<=R;j++){ p=(a[j]&bin[i])?1:0; if(num[ch[px[j]][p]]-num[ch[py[j]][p]]>0) px[j]=ch[px[j]][p],py[j]=ch[py[j]][p]; else px[j]=py[j]=0; } }else{ for(int j=L;j<=R;j++){ p=(a[j]&bin[i])?1:0; if(num[ch[px[j]][p^1]]-num[ch[py[j]][p^1]]>0) px[j]=ch[px[j]][p^1],py[j]=ch[py[j]][p^1]; else px[j]=py[j]=0; }ans|=bin[i]; } }return ans; } }T; int main() { //freopen("t1.in","r",stdin); scanf("%d%d",&n,&m); for(int i=31;i>=0;i--) bin[i]=(1<<i); for(int i=1;i<=n;i++) a[i]=gint(); T.init(); for(int i=1;i<=m;i++) b[i]=gint(),T.insert(b[i],i-1,i,1); int Q,u,d,l,r,K; scanf("%d",&Q); for(int q=1;q<=Q;q++) { u=gint(),d=gint(),l=gint(),r=gint(),K=gint(); printf("%d\n",T.query(u,d,l-1,r,K)); } return 0; }