P4735 最大异或和 题解
传送门:P4735 最大异或和
本题解致力于阐述三种不同方法。它们之间联系紧密,算法优秀程度也层层递进。
一、可持久化 01-Trie(朴素版)
先推一波式子:
还记得 01-Trie 吗?智商
本题可以视为在操作 ② 里加一限制:
如果
普通 01-Trie 不满足相消性,不妨令
概述可持久化 01-Trie:
回顾可持久化数据结构的设计宗旨:在不破坏历史版本的情况下,新建尽量少的节点得到当前版本树。具体些:只沿用那些子树(包括本身)信息都未变化的节点。即使本身信息未变,但子树信息变化了,也要新开一个新节点。
插入
算法流程:设
利用相消性查询即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=600005;
int n,m;
int s[N];
int ch[N*25][2],sum[N*25];
int root[N],idx;
void insert(int x,int y,int i){
sum[x]=sum[y]+1;
for(int k=23;k>=0;k--){
int c=(s[i]>>k)&1;
ch[x][!c]=ch[y][!c];
ch[x][c]=++idx;
x=ch[x][c],y=ch[y][c];
sum[x]=sum[y]+1;
}
}
int query(int x,int y,int v){
int ans=0;
for(int k=23;k>=0;k--){
int c=(v>>k)&1;
if(sum[ch[x][!c]]-sum[ch[y][!c]]) ans+=(1<<k),x=ch[x][!c],y=ch[y][!c];
else x=ch[x][c],y=ch[y][c];
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&s[i]),s[i]^=s[i-1];
root[0]=++idx,insert(root[0],0,0);
for(int i=1;i<=n;i++) root[i]=++idx,insert(root[i],root[i-1],i);
while(m--){
char ch[2];scanf("%s",ch);
if(ch[0]=='A'){
int x;scanf("%d",&x);
root[++n]=++idx;
s[n]=s[n-1]^x;
insert(root[n],root[n-1],n);
}else{
int l,r,x;scanf("%d%d%d",&l,&r,&x);
l--,r--;
printf("%d\n",query(root[r],(l?root[l-1]:0),s[n]^x));
}
}
return 0;
}
二、可持久化 01-Trie(升级版)
可持久化数据结构
我们能否只利用
我们用 sum[ch[x][!c]]-sum[ch[y][!c]]>=0 改成 ver[ch[x][!c]]>=L 即可避免使用
直白些,就是判断是否存在
那怎么求 ver[x]=i 即可!
代码:
#include<bits/stdc++.h>
using namespace std;
#define FIO
struct IO{
#ifdef FIO
const static int BUFSIZE=1<<20;char buf[BUFSIZE],obuf[BUFSIZE],*p1,*p2,*pp;inline char getchar(){return(p1==p2&&(p2=(p1=buf)+fread(buf,1,BUFSIZE,stdin),p1==p2)?EOF:*p1++);}inline void putchar(char x){((pp-obuf==BUFSIZE&&(fwrite(obuf,1,BUFSIZE,stdout),pp=obuf)),*pp=x,pp++);}inline void flush(){fwrite(obuf,1,pp-obuf,stdout);}IO(){fwrite("Warning: Macro 'FIO' has been defined, keyboard input will be ignored.\n",1,71,stderr);p1=buf,p2=buf,pp=obuf;}~IO(){fwrite(obuf,1,pp-obuf,stdout);}
#else
int(*getchar)()=&::getchar;int(*putchar)(int)=&::putchar;inline void flush(){};
#endif
string sep=" ";int k=2;template<typename Tp,typename enable_if<is_integral<Tp>::value>::type* =nullptr>inline int read(Tp&s){int f=1;char ch=getchar();s=0;while(!isdigit(ch)&&ch!=EOF)f=(ch=='-'?-1:1),ch=getchar();while(isdigit(ch))s=s*10+(ch^48),ch=getchar();s*=f;return ch!=EOF;}template<typename Tp,typename enable_if<is_floating_point<Tp>::value>::type* =nullptr>inline int read(Tp&s){int f=1;char ch=getchar();s=0;while(!isdigit(ch)&&ch!=EOF&&ch!='.')f=(ch=='-'?-1:1),ch=getchar();while(isdigit(ch))s=s*10+(ch^48),ch=getchar();if(ch==EOF)return false;if(ch=='.'){Tp eps=0.1;ch=getchar();while(isdigit(ch))s=s+(ch^48)*eps,ch=getchar(),eps/=10;}s*=f;return ch!=EOF;}inline int read(char&c){char ch=getchar();while(isspace(ch)&&ch!=EOF)ch=getchar();if(ch!=EOF)c=ch;return ch!=EOF;}inline int read(char*c){char ch=getchar();while(isspace(ch)&&ch!=EOF)ch=getchar();while(!isspace(ch)&&ch!=EOF)*(c++)=ch,ch=getchar();return ch!=EOF;}inline int read(string&s){s.clear();char ch=getchar();while(isspace(ch)&&ch!=EOF)ch=getchar();while(!isspace(ch)&&ch!=EOF)s+=ch,ch=getchar();return ch!=EOF;}inline int getline(char*c,const char&ed='\n'){char ch=getchar();while(ch!=ed&&ch!=EOF)*(c++)=ch,ch=getchar();return ch!=EOF;}inline int getline(string&s,const char&ed='\n'){s.clear();char ch=getchar();while(ch!=ed&&ch!=EOF)s+=ch,ch=getchar();return ch!=EOF;}template<typename Tp=int>inline Tp read(){Tp x;read(x);return x;}template<typename Tp,typename...Ts>int read(Tp&x,Ts&...val){return read(x)&&read(val...);}template<typename Tp,typename enable_if<is_integral<Tp>::value>::type* =nullptr>IO&write(Tp x){if(x<0)putchar('-'),x=-x;static char sta[20];int top=0;do sta[top++]=x%10+'0',x/=10;while(x);while(top)putchar(sta[--top]);return*this;}inline IO&write(const string&str){for(char ch:str)putchar(ch);return*this;}inline IO&write(const char*str){while(*str!='\0')putchar(*(str++));return*this;}inline IO&write(char*str){return write((const char*)str);}inline IO&write(const char&ch){return putchar(ch),*this;}template<typename Tp,typename enable_if<is_floating_point<Tp>::value>::type* =nullptr>inline IO&write(Tp x){const static long long pow10[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,1000000000000,10000000000000,100000000000000,1000000000000000,10000000000000000,100000000000000000,100000000000000000,100000000000000000};const auto&n=pow10[k];if(x==0){putchar('0'),putchar('.');for(int i=1;i<=k;++i)putchar('0');return*this;}if(x<0)putchar('-'),x=-x;long long d=(long long)(x+1e-12),y=(long long)(x*n+0.5);write(d),putchar('.');static char sta[20];int top=0;for(;top<k;y/=10)sta[top++]=y%10^48;while(top)putchar(sta[--top]);return*this;}template<typename Tp,typename...Ts>inline IO&write(Tp x,Ts...val){write(x);write(sep);write(val...);return*this;}template<typename...Ts>inline IO&writeln(Ts...val){write(val...);putchar('\n');return*this;}inline IO&writeln(void){putchar('\n');return*this;}template<typename Tp>inline IO&writeWith(Tp x,const string&s){write(x),write(s);return*this;}inline IO&setsep(const string&s){return sep=s,*this;}inline IO&setprecision(const int&K){return k=K,*this;}}io;
const int N=600005;
int n,m;
int s[N];
int ch[N*25][2];
int root[N],idx;
int ver[N*25];
inline void insert(int x,int y,int i){
ver[x]=i;
for(int k=23;k>=0;k--){
int c=(s[i]>>k)&1;
ch[x][!c]=ch[y][!c];
ch[x][c]=++idx;
x=ch[x][c],y=ch[y][c];
ver[x]=i;
}
}
inline int query(int x,int L,int v){
int ans=0;
for(int k=23;k>=0;k--){
int c=(v>>k)&1;
if(ver[ch[x][!c]]>=L) x=ch[x][!c],ans+=(1<<k);
else x=ch[x][c];
}
return ans;
}
int main(){
io.read(n,m);
for(int i=1;i<=n;i++) io.read(s[i]),s[i]^=s[i-1];
ver[0]=-1;
root[0]=++idx,insert(root[0],0,0);
for(int i=1;i<=n;i++) root[i]=++idx,insert(root[i],root[i-1],i);
while(m--){
char ch;io.read(ch);
if(ch=='A'){
io.read(s[++n]);
s[n]^=s[n-1];
root[n]=++idx,insert(root[n],root[n-1],n);
}else{
int l,r,x;io.read(l,r,x);
io.writeln(query(root[r-1],l-1,s[n]^x));
}
}
return 0;
}
三、离线 + 01-Trie
法二中的函数 query 只与
代码:
#include<bits/stdc++.h>
using namespace std;
#define FIO
struct IO{
#ifdef FIO
const static int BUFSIZE=1<<20;char buf[BUFSIZE],obuf[BUFSIZE],*p1,*p2,*pp;inline char getchar(){return(p1==p2&&(p2=(p1=buf)+fread(buf,1,BUFSIZE,stdin),p1==p2)?EOF:*p1++);}inline void putchar(char x){((pp-obuf==BUFSIZE&&(fwrite(obuf,1,BUFSIZE,stdout),pp=obuf)),*pp=x,pp++);}inline void flush(){fwrite(obuf,1,pp-obuf,stdout);}IO(){fwrite("Warning: Macro 'FIO' has been defined, keyboard input will be ignored.\n",1,71,stderr);p1=buf,p2=buf,pp=obuf;}~IO(){fwrite(obuf,1,pp-obuf,stdout);}
#else
int(*getchar)()=&::getchar;int(*putchar)(int)=&::putchar;inline void flush(){};
#endif
string sep=" ";int k=2;template<typename Tp,typename enable_if<is_integral<Tp>::value>::type* =nullptr>inline int read(Tp&s){int f=1;char ch=getchar();s=0;while(!isdigit(ch)&&ch!=EOF)f=(ch=='-'?-1:1),ch=getchar();while(isdigit(ch))s=s*10+(ch^48),ch=getchar();s*=f;return ch!=EOF;}template<typename Tp,typename enable_if<is_floating_point<Tp>::value>::type* =nullptr>inline int read(Tp&s){int f=1;char ch=getchar();s=0;while(!isdigit(ch)&&ch!=EOF&&ch!='.')f=(ch=='-'?-1:1),ch=getchar();while(isdigit(ch))s=s*10+(ch^48),ch=getchar();if(ch==EOF)return false;if(ch=='.'){Tp eps=0.1;ch=getchar();while(isdigit(ch))s=s+(ch^48)*eps,ch=getchar(),eps/=10;}s*=f;return ch!=EOF;}inline int read(char&c){char ch=getchar();while(isspace(ch)&&ch!=EOF)ch=getchar();if(ch!=EOF)c=ch;return ch!=EOF;}inline int read(char*c){char ch=getchar();while(isspace(ch)&&ch!=EOF)ch=getchar();while(!isspace(ch)&&ch!=EOF)*(c++)=ch,ch=getchar();return ch!=EOF;}inline int read(string&s){s.clear();char ch=getchar();while(isspace(ch)&&ch!=EOF)ch=getchar();while(!isspace(ch)&&ch!=EOF)s+=ch,ch=getchar();return ch!=EOF;}inline int getline(char*c,const char&ed='\n'){char ch=getchar();while(ch!=ed&&ch!=EOF)*(c++)=ch,ch=getchar();return ch!=EOF;}inline int getline(string&s,const char&ed='\n'){s.clear();char ch=getchar();while(ch!=ed&&ch!=EOF)s+=ch,ch=getchar();return ch!=EOF;}template<typename Tp=int>inline Tp read(){Tp x;read(x);return x;}template<typename Tp,typename...Ts>int read(Tp&x,Ts&...val){return read(x)&&read(val...);}template<typename Tp,typename enable_if<is_integral<Tp>::value>::type* =nullptr>IO&write(Tp x){if(x<0)putchar('-'),x=-x;static char sta[20];int top=0;do sta[top++]=x%10+'0',x/=10;while(x);while(top)putchar(sta[--top]);return*this;}inline IO&write(const string&str){for(char ch:str)putchar(ch);return*this;}inline IO&write(const char*str){while(*str!='\0')putchar(*(str++));return*this;}inline IO&write(char*str){return write((const char*)str);}inline IO&write(const char&ch){return putchar(ch),*this;}template<typename Tp,typename enable_if<is_floating_point<Tp>::value>::type* =nullptr>inline IO&write(Tp x){const static long long pow10[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,1000000000000,10000000000000,100000000000000,1000000000000000,10000000000000000,100000000000000000,100000000000000000,100000000000000000};const auto&n=pow10[k];if(x==0){putchar('0'),putchar('.');for(int i=1;i<=k;++i)putchar('0');return*this;}if(x<0)putchar('-'),x=-x;long long d=(long long)(x+1e-12),y=(long long)(x*n+0.5);write(d),putchar('.');static char sta[20];int top=0;for(;top<k;y/=10)sta[top++]=y%10^48;while(top)putchar(sta[--top]);return*this;}template<typename Tp,typename...Ts>inline IO&write(Tp x,Ts...val){write(x);write(sep);write(val...);return*this;}template<typename...Ts>inline IO&writeln(Ts...val){write(val...);putchar('\n');return*this;}inline IO&writeln(void){putchar('\n');return*this;}template<typename Tp>inline IO&writeWith(Tp x,const string&s){write(x),write(s);return*this;}inline IO&setsep(const string&s){return sep=s,*this;}inline IO&setprecision(const int&K){return k=K,*this;}}io;
const int N=600005;
int n,m;
int s[N];
int ch[N*25][2];
int idx=1;
int ver[N*25];
int head[N],nxt[N],L[N],X[N],id[N],tot;
int qct,ans[N];
inline void add(int u,int L1,int X1,int id1){
L[++tot]=L1,X[tot]=X1,id[tot]=id1;
nxt[tot]=head[u];
head[u]=tot;
}
inline void insert(int x,int i){
ver[x]=i;
for(int k=23;k>=0;k--){
int c=(s[i]>>k)&1;
if(!ch[x][c]) ch[x][c]=++idx;
ver[x=ch[x][c]]=i;
}
}
inline int query(int x,int L,int v){
int ans=0;
for(int k=23;k>=0;k--){
int c=(v>>k)&1;
if(ver[ch[x][!c]]>=L) x=ch[x][!c],ans+=(1<<k);
else x=ch[x][c];
}
return ans;
}
int main(){
memset(head,-1,sizeof(head));
io.read(n,m);
for(int i=1;i<=n;i++) io.read(s[i]),s[i]^=s[i-1];
ver[0]=-1;
while(m--){
char ch[2];io.read(ch);
if(ch[0]=='A'){
io.read(s[++n]);
s[n]^=s[n-1];
}else{
int l,r,x;io.read(l,r,x);
add(r-1,l,s[n]^x,++qct);
}
}
for(int i=0;i<=n;i++){
insert(1,i);
for(int k=head[i];~k;k=nxt[k]) ans[id[k]]=query(1,L[k]-1,X[k]);
}
for(int i=1;i<=qct;i++) io.writeln(ans[i]);
return 0;
}
本代码抢到了最优解第