HDU4757:Tree——题解
http://acm.hdu.edu.cn/showproblem.php?pid=4757
给一棵有点值的树,每次询问u~v的最短路当中的一个点的点权异或z最大值。
前置技能:HDU4825
前置技能:BZOJ3261(可持久化trie)
默认你会如何建可持久化trie跑贪心了。
emmmm既然你已经懂了那还说啥,u~v的链可以剖成u~lca和v~lca,即每次询问这两个链和z异或的最大值即可。
PS:注意询问的时候区间左端点-1,即询问的是rt[fa(lca)]~rt[u/v]。
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<algorithm> #include<cctype> using namespace std; const int N=1e5+5; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct trie{ int son[2],sum; }tr[40*N]; struct node{ int to,nxt; }e[N*2]; int tot,a[N],rt[N],pool,cnt,head[N]; int dep[N],anc[N][20]; inline void add(int u,int v){ e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; } inline void addtwo(int u,int v){ add(u,v);add(v,u); } void insert(int y,int &x,int k,int now){ tr[x=++pool]=tr[y]; tr[x].sum++; if(now<0)return; bool p=k&(1<<now); insert(tr[y].son[p],tr[x].son[p],k,now-1); return; } int query(int nl,int nr,int k,int now){ if(now<0)return 0; bool p=k&(1<<now); int delta=tr[tr[nr].son[p^1]].sum-tr[tr[nl].son[p^1]].sum; if(delta>0)return (1<<now)+query(tr[nl].son[p^1],tr[nr].son[p^1],k,now-1); else return query(tr[nl].son[p],tr[nr].son[p],k,now-1); } void dfs(int u,int f){ anc[u][0]=f; for(int k=1;k<=18;k++) anc[u][k]=anc[anc[u][k-1]][k-1]; dep[u]=dep[f]+1; insert(rt[f],rt[u],a[u],15); for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(v!=f)dfs(v,u); } return; } inline int LCA(int i,int j){ if(dep[i]<dep[j])swap(i,j); for(int k=18;k>=0;k--){ if(dep[anc[i][k]]>=dep[j])i=anc[i][k]; } if(i==j)return i; for(int k=18;k>=0;k--){ if(anc[i][k]!=anc[j][k])i=anc[i][k],j=anc[j][k]; } return anc[i][0]; } inline void init(){ memset(tr,0,sizeof(tr)); memset(rt,0,sizeof(rt)); memset(head,0,sizeof(head)); tot=1;cnt=pool=0; } int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF){ init(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<n;i++)addtwo(read(),read()); dfs(1,0); for(int i=1;i<=m;i++){ int u=read(),v=read(),x=read(),lca=LCA(u,v),fa=anc[lca][0]; printf("%d\n",max(query(rt[fa],rt[u],x,15), query(rt[fa],rt[v],x,15))); } } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++