[THUSC2015] 异或运算

\(\text{Problem}:\)[THUSC2015] 异或运算

\(\text{Solution}:\)

发现 \(m\) 远大于 \(n\),故考虑对 \(y\) 这一维建出可持久化 \(\text{Trie}\) 树,查询时用 \(x\) 这一维在差分后的 \(\text{Trie}\) 树上匹配。

先将求第 \(k\) 小转化为第 \(k\) 大。考虑在每一层对于 \(x\) 算出与 \(x_{i}\) 走相同转移边的答案 \(val\),若 \(val<k\),则这棵子树答案都偏小,故将这层贡献给最终答案,并将 \(k\) 减去 \(val\),转移时走相反边即可。总时间复杂度 \(O(31np)\)

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=300010;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,m,Q,a[N],b[N];
int root[N],cnt,ch[N*32][2],sum[N*32];
inline void Insert(int pre,int x,int w)
{
	for(ri int i=30;~i;i--)
	{
		sum[x]=sum[pre]+1;
		memcpy(ch[x],ch[pre],sizeof(ch[pre]));
		int p=(w>>i)&1;
		ch[x][p]=++cnt;
		x=ch[x][p], pre=ch[pre][p];
	}
	sum[x]=sum[pre]+1;
}
int L[N],R[N];
inline int Ask(int u,int d,int l,int r,int k)
{
	int ans=0;
	for(ri int i=u;i<=d;i++) L[i]=root[l-1], R[i]=root[r];
	for(ri int i=30;~i;i--)
	{
		int val=0;
		for(ri int j=u;j<=d;j++) val+=sum[ch[R[j]][(a[j]>>i)&1]]-sum[ch[L[j]][(a[j]>>i)&1]];
		int p=0;
		if(k>val) k-=val, ans+=(1<<i), p=1;
		for(ri int j=u;j<=d;j++) L[j]=ch[L[j]][(a[j]>>i)&1^p], R[j]=ch[R[j]][(a[j]>>i)&1^p];
	}
	return ans;
}
signed main()
{
	n=read(), m=read();
	for(ri int i=1;i<=n;i++) a[i]=read();
	for(ri int i=1;i<=m;i++) b[i]=read();
	for(ri int i=1;i<=m;i++) root[i]=++cnt, Insert(root[i-1],root[i],b[i]);
	Q=read();
	for(ri int i=1;i<=Q;i++)
	{
		int u,d,l,r,k;
		u=read(), d=read(), l=read(), r=read(), k=read();
		k=(d-u+1)*(r-l+1)-k+1;
		printf("%d\n",Ask(u,d,l,r,k));
	}
	return 0;
}
posted @ 2021-05-02 16:43  zkdxl  阅读(71)  评论(0编辑  收藏  举报