P4592 [TJOI2018]异或

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4592 [TJOI2018]异或相关的知识,希望对你有一定的参考价值。

P4592 [TJOI2018]异或

题意:

现在有一颗以 1 为根节点的由 n 个节点组成的树,节点从 1 至 n 编号。树上每个节点上都有一个权值 vi。现在有 q 次操作,操作如下:
1 x z:查询节点 x 的子树中的节点权值与 z 异或结果的最大值。
2 x y z:查询节点 x 到节点 y 的简单路径上的节点的权值与 z 异或结果最大值。

题解:

很明显的可持久化01Trie
对于第一个问题,直接按照时间戳(DFS序)建立点权的可持久化01Trie,每次查询就是对区间[dfn[u],dfn[u]+siz[u]-1]的询问,(u的所有儿子都被包含在这个区间内)
关于第二个问题,我们都知道对于u->v的路径,我们可以拆分成rt到u,rt到v,rt到lca,rt到fa[lca](老套路了)这四套路径,建立rt到所有点的可持久化01Trie,然后查询这四条路找到答案
相当于对于两问建了两个可持久化01Trie

代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){
   ll s=0,w=1ll;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
void rd_test(){
	#ifdef ONLINE_JUDGE
	#else
		startTime = clock(); //计时开始
        freopen("in.txt","r",stdin);
	#endif
}
void Time_test(){
	#ifdef ONLINE_JUDGE
	#else
		endTime = clock(); //计时结束
   		printf("\\n运行时间为:%lfs\\n",(double)(endTime - startTime) / CLOCKS_PER_SEC);
	#endif
}
int n,m,sum,dep[200001],a[200001],ktot,size[200001],tpos[200001],pre[200001],head[200001],tot,f[200001][25];
struct edge{
    int to,next;
}g[1000001];
inline void made(int from,int to){
    g[++tot].to=to;g[tot].next=head[from];head[from]=tot;
}
struct Trie{
    int n,son[10000001][2],cnt=1,sum,root[200001],ct[10000001];
    void ins(int &rt,int x,int T){
        ct[++cnt]=ct[rt]+1;son[cnt][0]=son[rt][0];
        son[cnt][1]=son[rt][1];rt=cnt;
        if (T==-1) return;
        register bool y=(x>>T)&1;
        ins(son[rt][y],x,T-1);
    }
    inline void insert(int pre,int rt,int x){
        root[rt]=root[pre];
        ins(root[rt],x,30);
    }
    int QUE(int i,int j,int x,int T){//序列版
        if (T==-1) return 0;
        register bool y=(x>>T)&1;
        if (ct[son[j][1^y]]>ct[son[i][1^y]]) return ((1<<T)+QUE(son[i][1^y],son[j][1^y],x,T-1));
        else return QUE(son[i][y],son[j][y],x,T-1);
    }
    int queryxx(int i,int j,int lca,int fa,int x,int T){//树上差分版
        if (T==-1) return 0;
        register bool y=(x>>T)&1;
        if (ct[son[j][1^y]]+ct[son[i][1^y]]>ct[son[lca][1^y]]+ct[son[fa][1^y]]) 
			return ((1<<T)+queryxx(son[i][1^y],son[j][1^y],son[lca][1^y],son[fa][1^y],x,T-1));
        else return queryxx(son[i][y],son[j][y],son[lca][y],son[fa][y],x,T-1);
    }
    int queryx(int i,int j,int lc,int flc,int x,int T){
        return queryxx(root[i],root[j],root[lc],root[flc],x,T);
    }
    inline int query(int l,int r,int x){
        return QUE(root[l-1],root[r],x,30);
    }
}tr1,tr2;
void dfs0(int u,int fa){
    dep[u]=dep[fa]+1;
	f[u][0]=fa;
	tpos[u]=++ktot;
	pre[ktot]=u;
    tr1.insert(fa,u,a[u]);
	size[u]=1;
    
	for (int i=1;i<=21;i++) f[u][i]=f[f[u][i-1]][i-1];
    
	for (int i=head[u];i;i=g[i].next){
        int v=g[i].to;
        if (v==fa) continue;
        dfs0(v,u);size[u]+=size[v];
    }
}
inline int LCA(int x,int y){
    if (dep[x]<dep[y]) swap(x,y);
    for (int i=21;i>=0;i--){
        if (dep[f[x][i]]>=dep[y]) x=f[x][i];
    }
    if (x==y) return x;
    for (int i=21;i>=0;i--){
        if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
int main(){
	rd_test();
    n=read();m=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<n;i++){
    	int x=read(),y=read();
    	made(x,y);made(y,x);
    }
    dfs0(1,0);
    for (int i=1;i<=n;i++){
    	tr2.insert(i-1,i,a[pre[i]]);
    }
    while (m--){
        int opt=read();
        if (opt==1){
            int x=read(),y=read();
            printf("%d\\n",tr2.query(tpos[x],tpos[x]+size[x]-1,y));
        }else{
            int x=read(),y=read(),z=read();
			int lca=LCA(x,y);
            printf("%d\\n",tr1.queryx(x,y,lca,f[lca][0],z,30));
        }
    }
    Time_test();
}

写的另一个还没改完的代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
//Fe~Jozky
clock_t startTime, endTime;
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){
   ll s=0,w=1ll;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
void rd_test(){
	#ifdef ONLINE_JUDGE
	#else
		startTime = clock(); //计时开始
        freopen("in.txt","r",stdin);
	#endif
}
void Time_test(){
	#ifdef ONLINE_JUDGE
	#else
		endTime = clock(); //计时结束
   		printf("\\n运行时间为:%lfs\\n",(double)(endTime - startTime) / CLOCKS_PER_SEC);
	#endif
}
const int maxn=3e5+9;
vector<int>vec[maxn];
struct tree{
	int cnt=0;
	int ch[3];
}tr[maxn*40];
int rt[maxn];
int a[maxn];
int fa[maxn][25], dep[maxn], lg[maxn];
int rtnum=0;
int dfn[maxn],predfn[maxn];
int dfnnum=0;
int siz[maxn];
int newa[maxn];
void insert(int now,int pre,int x){
	for(int i=30;i>=0;i--){
		int c=((x>>i)&1);
		tr[now].ch[c^1]=tr[pre].ch[c^1];
		tr[now].ch[c]=++rtnum;
		
		now=tr[now].ch[c];
		pre=tr[pre].ch[c];
		tr[now].cnt=tr[pre].cnt+1;
	}
}
int query(int L,int R,int x){
	int sum=0;
	for(int i=30;i>=0;i--){
		int c=((x>>i)&1);
		if(tr[tr[R].ch[c^1]].cnt>tr[tr[L].ch[c^1]].cnt){
			sum+=(1<<i);
			L=tr[L].ch[cP4592 [TJOI2018]异或  树链剖分 01trie

可持久化3--可持久化01Trie

TJOI2018 异或

[TJOI2018]异或

BZOJ5338 [TJOI2018] Xor 可持久化Trie树dfs序

bzoj4888: [Tjoi2017]异或和 BIT-乱搞