• [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
    ",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
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    mysql的复制
    web页面请求历程
    django工作原理简介
    http协议
    路由器和交换机的区别
    OSI七层模型
    TCP/IP协议总结
    IO复用
    僵尸进程和孤儿进程
    java源代码如何打成jar包
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9201039.html
Copyright © 2020-2023  润新知