[TJOI2018]异或【可持久化Trie+树剖】

[TJOI2018]异或
把树剖套的线段树换成可持久化\(Trie\)树就结束了

int val[Maxm], ch[Maxm][2], T_cnt;
void ins(int i, int o, int p, int x, int now){
	if(now < 0) {val[o]=i; return;} 
	int k=x>>now&1; if(ch[p][k^1]) ch[o][k^1]=ch[p][k^1]; ch[o][k]=++T_cnt;
	ins(i, ch[o][k], ch[p][k], x, now-1); val[o]=max(val[ch[o][0]], val[ch[o][1]]);
}

int fa[Maxn], top[Maxn], dfn[Maxn], rnk[Maxn], cnt, sz[Maxn], hson[Maxn], dep[Maxn];
void dfs1(int u){ sz[u]=1;
	for(int i=head[u], v; i; i=nxt[i])if((v=to[i]) !=fa[u]){
		fa[v]=u, dep[v]=dep[u]+1; dfs1(v); 
		sz[u]+=sz[v]; if(sz[v] > sz[hson[u]]) hson[u]=v;
	}
}
void dfs2(int u, int anc){
	top[u]=anc; dfn[u]=++cnt; rnk[cnt]=u; if(hson[u]) dfs2(hson[u], anc); else return ;
	for(int i=head[u], v; i; i=nxt[i]) if((v=to[i]) != fa[u] && v != hson[u]) dfs2(v, v);
}
int query(int L, int o, int x, int now){
	if(now < 0) return v[rnk[val[o]]]^x; int k=x>>now&1;
	if(val[ch[o][k^1]] >= L) return query(L, ch[o][k^1], x, now-1);
	return query(L, ch[o][k], x, now-1);
}

void cal(int u, int v, int z){
	int tu=top[u], tv=top[v], ans=0;
	while(tu != tv){
		if(dep[tu] < dep[tv]) swap(u, v), swap(tu, tv);
		ans=max(ans, query(dfn[tu], rt[dfn[u]], z, 30));
		u=fa[tu], tu=top[u];
	}
	if(dep[u] < dep[v]) swap(u, v); ans=max(ans, query(dfn[v], rt[dfn[u]], z, 30));
	printf("%d\n", ans);
}
void solve(){
	n=read(), q=read();
	for(int i=1; i <= n; i++) v[i]=read();
	for(int i=1, u, v; i < n; i++) u=read(), v=read(), add(u, v), add(v, u);
	dfs1(1); dfs2(1, 1); 
	for(int i=1; i <= n; i++) rt[i]=++T_cnt, ins(i, rt[i], rt[i-1], v[rnk[i]], 30);
	while(q--){
		int cmd=read(), x=read(), y=read(), z;
		if(cmd == 1) printf("%d\n", query(dfn[x], rt[dfn[x]+sz[x]-1], y, 30));
		else z=read(), cal(x, y, z);
	}
}
posted @ 2018-07-11 22:27  zerolt  阅读(162)  评论(0编辑  收藏  举报