【题解】hdu4757 【TJOI2018】异或

题目链接

题目大意:有一颗树,有点权,每次询问:一条路径(x->y)中与(z)异或的最大值,或是以(x)为根的子树中与(y)异或的最大值。

树剖……还是算了。

观察到,子树的(dfn)序是连续的一段区间。于是我们可以预处理(dfs)序来解决这个问题。

第二问,我们可以求两点的最近公共祖先,做一个树上差分来实现。

维护两颗可持久化(Trie.)一个维护(dfs)序,一个维护(x->root).

当然(HDU)的那个题是没有第一个操作的,但是是多组询问。

(HDU:)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
int n,m,siz[MAXN],dfn[MAXN],f[MAXN][25];
int dep[MAXN],head[MAXN<<1],tot,dfstime;
int pre[MAXN],a[MAXN];
struct edge{
	int nxt,to;
}e[MAXN<<1];
inline void add(int x,int y){
	e[++tot].to=y;
	e[tot].nxt=head[x];
	head[x]=tot;
}
struct Trie{
	int son[MAXN<<5][2],ct[MAXN<<5],root[MAXN],cnt=1;
	void Insert(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;
		bool y=(x>>T)&1;
		Insert(son[rt][y],x,T-1);
	}
	void Ins(int pre,int rt,int x){
		root[rt]=root[pre];
		Insert(root[rt],x,30);
	}
	int Q(int i,int j,int x,int T){
		if(T==-1)return 0;
		int y=(x>>T)&1;
		if(ct[son[j][1^y]]>ct[son[i][1^y]])return ((1<<T)+Q(son[i][1^y],son[j][1^y],x,T-1));
		return Q(son[i][y],son[j][y],x,T-1);
	} 
	int QT(int i,int j,int lc,int flc,int x,int T){
		if(T==-1)return 0;
		int y=(x>>T)&1;
		if(ct[son[i][1^y]]+ct[son[j][1^y]]>ct[son[lc][1^y]]+ct[son[flc][1^y]])return ((1<<T)+QT(son[i][1^y],son[j][1^y],son[lc][1^y],son[flc][1^y],x,T-1));
		else return QT(son[i][y],son[j][y],son[lc][y],son[flc][y],x,T-1);
	}
	int query(int i,int j,int x){
		return Q(root[i-1],root[j],x,30);
	}
	int UQT(int i,int j,int lc,int flc,int x){
		return QT(root[i],root[j],root[lc],root[flc],x,30);
	}
	void clear(){
		cnt=1;
		memset(root,0,sizeof(root));
		memset(ct,0,sizeof(ct));
		memset(son,0,sizeof(son));
	}
}tr1;
void dfs(int u,int fa){
	dep[u]=dep[fa]+1;siz[u]=1;
	pre[dfn[u]=++dfstime]=u;
	f[u][0]=fa;
	for(int i=1;i<=22;++i)f[u][i]=f[f[u][i-1]][i-1];
	tr1.Ins(fa,u,a[u]);
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa)continue;
		dfs(v,u);siz[u]+=siz[v];
	}
}
int LCA(int u,int v){
	if(dep[u]<dep[v])u^=v^=u^=v;
	for(int i=22;i>=0;--i)
		if(dep[f[u][i]]>=dep[v])u=f[u][i];
	if(u==v)return u;
	for(int i=22;i>=0;--i)
		if(f[u][i]!=f[v][i])
			u=f[u][i],v=f[v][i];
	return f[u][0];
}
void work(){
	int x,y,z;
	scanf("%d%d%d",&x,&y,&z);
	int A=LCA(x,y);
	printf("%d
",tr1.UQT(x,y,A,f[A][0],z));
}
int main(){
	while(~scanf("%d%d",&n,&m)){
		for(int i=1;i<=n;++i)scanf("%d",&a[i]);
		for(int i=1;i<n;++i){
			int u,v;
			scanf("%d%d",&u,&v);
			add(u,v);add(v,u);
		}
		dfs(1,0);
		for(;m;m--)work();
		memset(a,0,sizeof(a));
		dfstime=0;tot=0;
		memset(dfn,0,sizeof(dfn));
		memset(pre,0,sizeof(pre));
		memset(dep,0,sizeof(dep));
		memset(siz,0,sizeof(siz));
		memset(f,0,sizeof(f));
		memset(head,0,sizeof(head));
		tr1.clear();
	} 
	
	return 0;
}

(Luogu:)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
inline int read(){
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return w==-1?-s:s;
}
int n,m,dep[MAXN],a[MAXN],siz[MAXN],dfn[MAXN];
int tot,ktot,head[MAXN<<1],pre[MAXN],f[MAXN][25];
struct edge{
	int nxt,to;
}e[MAXN<<1];
inline void add(int x,int y){
	e[++tot].to=y;
	e[tot].nxt=head[x];
	head[x]=tot;
}
struct Trie{
	int son[MAXN<<5][2],cnt=1,root[MAXN],ct[MAXN<<5];
	void Insert(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;
		bool y=(x>>T)&1;
		Insert(son[rt][y],x,T-1);
	}
	inline void Ins(int pre,int rt,int x){
		root[rt]=root[pre];
		Insert(root[rt],x,30);
	}
	int Q(int i,int j,int x,int T){
		if(T==-1)return 0;
		bool y=(x>>T)&1;
		if(ct[son[j][1^y]]>ct[son[i][1^y]])return ((1<<T)+Q(son[i][1^y],son[j][1^y],x,T-1));
		return Q(son[i][y],son[j][y],x,T-1);
	}
	int QT(int i,int j,int lc,int flc,int x,int T){
		if(T==-1)return 0;
		bool y=(x>>T)&1;
		if(ct[son[j][1^y]]+ct[son[i][1^y]]>ct[son[lc][1^y]]+ct[son[flc][1^y]])return ((1<<T)+QT(son[i][1^y],son[j][1^y],son[lc][1^y],son[flc][1^y],x,T-1));
		else return QT(son[i][y],son[j][y],son[lc][y],son[flc][y],x,T-1);
	}
	int query(int l,int r,int x){return Q(root[l-1],root[r],x,30);}
	int UQT(int i,int j,int lc,int flc,int x,int T){
		return QT(root[i],root[j],root[lc],root[flc],x,T);
	}
}tr1,tr2;
void dfs(int u,int fa){
	dep[u]=dep[fa]+1;f[u][0]=fa;
	dfn[u]=++ktot;pre[ktot]=u;
	tr1.Ins(fa,u,a[u]);siz[u]=1;
	for(int i=1;i<=22;++i)f[u][i]=f[f[u][i-1]][i-1];
	for(int i=head[u];i;i=e[i].nxt){
		int j=e[i].to;
		if(j==fa)continue;
		dfs(j,u);siz[u]+=siz[j];
	}
}
int LCA(int x,int y){
	if(dep[x]<dep[y])swap(x,y);
	for(int i=22;i>=0;--i)
		if(dep[f[x][i]]>=dep[y])x=f[x][i];
	if(x==y)return x;
	for(int i=22;i>=0;--i)
		if(f[x][i]!=f[y][i])
			x=f[x][i],y=f[y][i];
	return f[x][0];
}

int main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)a[i]=read();
	for(int i=1;i<n;++i){
		int u=read(),v=read();
		add(u,v);add(v,u);
	}
	dfs(1,0);
	for(int i=1;i<=n;++i)tr2.Ins(i-1,i,a[pre[i]]);
	for(;m;--m){
		int opt=read();
		if(opt==1){
			int x=read(),y=read();
			printf("%d
",tr2.query(dfn[x],dfn[x]+siz[x]-1,y));
		}
		else {
			int x=read(),y=read(),z=read(),A=LCA(x,y);
			printf("%d
",tr1.UQT(x,y,A,f[A][0],z,30));
		}
	}
	return 0;
} 
原文地址:https://www.cnblogs.com/h-lka/p/12494121.html