[BZOJ5338][TJOI2018]xor

bzoj
luogu

descirption

现在有一棵以 \(1\) 为根节点的由 \(n\) 个节点组成的树,树上每个节点上都有一个权值 \(v_i\) 。现在有 \(Q\) 次操作,操作如下:
\(1\;x\;y\) :查询节点 \(x\) 的子树中与 \(y\) 异或结果的最大值
\(2\;x\;y\;z\) :查询路径 \(x\)\(y\) 上点与 \(z\) 异或结果最大值

sol

正在写线性基的同学们醒一醒
可持久化\(Trie\)树。
和可持久化线段树没什么区别。
自己\(yy\)了一种比较好写的方法,可以不记\(l\)\(r\),只计当前的\(dep\)也就是二进制位。
为什么会有人写主席树强行\(\log^2n\)啊。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
const int N = 1e5+5;
struct node{int ch[2],sz;}t[N*35];
int n,m,v[N],val[N],mx,l,to[N<<1],nxt[N<<1],head[N],cnt;
int fa[N],dep[N],sz[N],son[N],top[N],dfn[N],rt[N],tot;
void link(int u,int v){
	to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
void dfs1(int u,int f){
	fa[u]=f;dep[u]=dep[f]+1;sz[u]=1;
	for (int e=head[u];e;e=nxt[e])
		if (to[e]!=f){
			dfs1(to[e],u),sz[u]+=sz[to[e]];
			if (sz[to[e]]>sz[son[u]]) son[u]=to[e];
		}
}
void dfs2(int u,int up){
	top[u]=up;dfn[u]=++cnt;
	if (son[u]) dfs2(son[u],up);
	for (int e=head[u];e;e=nxt[e])
		if (to[e]!=fa[u]&&to[e]!=son[u])
			dfs2(to[e],to[e]);
}
void modify(int &x,int p,int dep){
	t[++tot]=t[x];++t[x=tot].sz;
	if (!~dep) return;
	modify(t[x].ch[(p>>dep)&1],p,dep-1);
}
int query(int x,int y,int p,int dep){
	if (!~dep) return 0;
	int c=(p>>dep)&1;c^=1;
	if (t[t[x].ch[c]].sz-t[t[y].ch[c]].sz) return query(t[x].ch[c],t[y].ch[c],p,dep-1)|(1<<dep);
	c^=1;return query(t[x].ch[c],t[y].ch[c],p,dep-1);
}
int main(){
	n=gi();m=gi();
	for (int i=1;i<=n;++i) mx=max(mx,v[i]=gi());
	while ((1<<l)<mx) ++l;--l;
	for (int i=1;i<n;++i){
		int u=gi(),v=gi();
		link(u,v);link(v,u);
	}
	dfs1(1,0),cnt=0,dfs2(1,1);
	for (int i=1;i<=n;++i) val[dfn[i]]=v[i];
	for (int i=1;i<=n;++i) modify(rt[i]=rt[i-1],val[i],l);
	while (m--){
		int opt=gi();
		if (opt==1){
			int x=gi(),y=gi();
			printf("%d\n",query(rt[dfn[x]+sz[x]-1],rt[dfn[x]-1],y,l));
		}else{
			int x=gi(),y=gi(),z=gi(),ans=0;
			while (top[x]^top[y]){
				if (dep[top[x]]<dep[top[y]]) swap(x,y);
				ans=max(ans,query(rt[dfn[x]],rt[dfn[top[x]]-1],z,l));
				x=fa[top[x]];
			}
			if (dep[x]>dep[y]) swap(x,y);
			ans=max(ans,query(rt[dfn[y]],rt[dfn[x]-1],z,l));
			printf("%d\n",ans);
		}
	}
	return 0;
}
posted @ 2018-06-19 20:51  租酥雨  阅读(322)  评论(0编辑  收藏  举报