题解:P12573 [UOI 2023] An Array and XOR
_sayonara_ · · 题解
P12573 [UOI 2023] An Array and XOR
在博客食用阅读体验更佳。
题意:
给定长为
思路:
对二进制下每一位来观察,若区间内每个数第
想到建出 trie 树,区间内某一位的取值种类转化为树上节点的儿子数,令
既然有
既然要求某一位在区间内没有不同的值才能产生贡献,那么我们可以通过正反扫描一遍 trie 处理出每个数的每一位前面和后面最近的一个和他不一样的位置,分别记作
那么只有对于
不妨对右端点从大到小做扫描线,每扫到一个
当扫到询问的右端点
使用线段树或树状数组的话,单次询问和修改都是
然后我们为了平衡修改和查询的复杂度,考虑使用分块。分块维护最大值只要
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define _int __int128
#define ull unsigned long long
#define pii pair<int,int>
#define fst first
#define scd second
#define pq priority_queue
#define mkp make_pair
#define popcount(x) __builtin_popcount(x)
#define endl '\n'
inline int read(){
int k=0,f=1,c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())k=k*10+(c^48);
return k*f;
}
inline void write(int x){
if(x<10)putchar(x+'0');
else write(x/10),putchar(x%10+'0');
}
int n,m,k,t;
const int N = 1e5+10;
int a[N],ans[5*N];
int fl[N][55],fr[N][55],p[N][55];
struct trie{
int t[N*55][2],tot;
vector<int>v[55*N];
void init(){
for(int i=0;i<=tot;i++){
t[i][0]=t[i][1]=0;
v[i].clear();
}
tot=0;
}
void ins(int x,int id,bool typ){
int p=0;
for(int w=m-1;w>=0;w--){
int mk=(x>>w)&1ll;
if(!t[p][mk])t[p][mk]=++tot;
for(auto u:v[t[p][mk^1]]){
if(typ)fr[u][w]=id;
else fl[u][w]=id;
}
v[t[p][mk^1]].clear();
v[t[p][mk]].push_back(id);
p=t[p][mk];
}
}
}T;
int val[55];
bool cmp(int x,int y){
return val[x]<val[y];
}
struct qy{
int l,id;
};
vector<qy>q[N];
vector<int>s[N];
int L[N],R[N],pos[N],mx[N],kmx[N];
void change(int l,int v){
mx[l]=max(mx[l],v);
kmx[pos[l]]=max(kmx[pos[l]],v);
}
int query(int l,int r){
int p=pos[l],q=pos[r];
if(p==q){
int ans=0;
for(int i=l;i<=r;i++)ans=max(ans,mx[i]);
return ans;
}
int ans=0;
for(int i=l;i<=R[p];i++)ans=max(ans,mx[i]);
for(int i=p+1;i<q;i++)ans=max(ans,kmx[i]);
for(int i=L[q];i<=r;i++)ans=max(ans,mx[i]);
return ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
n=read(),k=read(),m=read();
t=sqrt(n);
for(int i=1;i<=t;i++){
L[i]=(i-1)*t+1;
R[i]=i*t;
}
if(R[t]<n)t++,L[t]=R[t-1]+1,R[t]=n;
for(int i=1;i<=t;i++){
for(int j=L[i];j<=R[i];j++)pos[j]=i;
}
for(int i=1;i<=n;i++){
a[i]=read();
}
T.init();
for(int i=1;i<=n;i++){
T.ins(a[i],i,1);
}
T.init();
for(int i=n;i>=1;i--){
T.ins(a[i],i,0);
}
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
p[i][j]=j;
if(!fr[i][j])fr[i][j]=n+1;
fl[i][j]++;fr[i][j]--;
s[fr[i][j]].push_back(i);
val[j]=fl[i][j];
}
sort(p[i],p[i]+m,cmp);
}
for(int i=1;i<=k;i++){
int l,r;
l=read(),r=read();
q[r].push_back({l,i});
}
for(int i=n;i>=1;i--){
for(auto v:s[i]){
int cur=0;
for(int j=0;j<m;j++){
int x=p[v][j];
if(fr[v][x]>=i){
cur|=(1ll<<x);
}
change(fl[v][x],cur);
}
}
for(auto [l,id]:q[i]){
ans[id]=query(1,l);
}
}
for(int i=1;i<=k;i++){
write(ans[i]);
putchar(endl);
}
return 0;
}