BZOJ2588 Spoj 10628. Count on a tree
Posted ljh2000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2588 Spoj 10628. Count on a tree相关的知识,希望对你有一定的参考价值。
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:BZOJ2588
正解:主席树上树
解题报告:
考虑主席树上树,每次build都是儿子在父亲的基础上build,然后查询的话就是对于x到y的路径,令$Tx$为$x$对应的线段树,那就是$T_x+T_y-T_{lca}-T_{fa[lca]}$。
//It is made by ljh2000 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> using namespace std; #define lc t[R].ls typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); const int MAXN = 200011; const int MAXM = 400011; int n,m,ecnt,first[MAXN],to[MAXM],next[MAXM],deep[MAXN],ans; int a[MAXN],b[MAXN],c[MAXN],L,f[MAXN][18],cnt,root[MAXN]; inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } struct node{ int ls,rs,num; }t[7000011]; inline int getint(){ int w=0,q=0; char c=getchar(); while((c<\'0\'||c>\'9\') && c!=\'-\') c=getchar(); if(c==\'-\') q=1,c=getchar(); while (c>=\'0\'&&c<=\'9\') w=w*10+c-\'0\',c=getchar(); return q?-w:w; } inline void build(int &rt,int last,int l,int r,int pos){ rt=++cnt; t[rt]=t[last]; t[rt].num++; if(l==r) return ; int mid=(l+r)>>1; if(pos<=mid) build(t[rt].ls,t[last].ls,l,mid,pos); else build(t[rt].rs,t[last].rs,mid+1,r,pos); } inline void dfs(int x,int fa){ build(root[x],root[fa],1,L,c[x]);//以父亲节点为last,更新主席树 //printf("%d\\n",cnt); for(int i=first[x];i;i=next[i]) { int v=to[i]; if(v==fa) continue; f[v][0]=x; deep[v]=deep[x]+1; dfs(v,x); } } inline int lca(int x,int y){ if(deep[x]<deep[y]) swap(x,y); int t=0; while((1<<t)<=deep[x]) t++; t--; for(int i=t;i>=0;i--) if(deep[x]-(1<<i)>=deep[y]) x=f[x][i]; if(x==y) return y; for(int i=t;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } inline int query(int x1,int x2,int j1,int j2,int l,int r,int k){ if(l==r) return l; int R=x1; int cp=t[lc].num; int mid=(l+r)>>1; R=x2; cp+=t[lc].num; R=j1; cp-=t[lc].num; R=j2; cp-=t[lc].num; if(k<=cp) return query(t[x1].ls,t[x2].ls,t[j1].ls,t[j2].ls,l,mid,k); else return query(t[x1].rs,t[x2].rs,t[j1].rs,t[j2].rs,mid+1,r,k-cp); } inline void work(){ n=getint(); m=getint(); for(int i=1;i<=n;i++) b[i]=a[i]=getint(); sort(b+1,b+n+1); L=unique(b+1,b+n+1)-b-1; for(int i=1;i<=n;i++) c[i]=lower_bound(b+1,b+L+1/*!!!*/,a[i])-b; int x,y,z,G; ans=0; for(int i=1;i<n;i++) { x=getint(); y=getint(); link(x,y); link(y,x); } deep[1]=1; dfs(1,0); for(int j=1;j<=17;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; while(m--) { x=getint(); y=getint(); z=getint(); x^=ans; G=lca(x,y); ans=b[ query(root[x],root[y],root[G],root[ f[G][0] ],1,L,z) ]; printf("%d",ans); if(m!=0) puts(""); } } int main() { work(); return 0; }
以上是关于BZOJ2588 Spoj 10628. Count on a tree的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]
BZOJ2588 Spoj 10628. Count on a tree
[BZOJ2588][Spoj 10628]Count on a tree
bzoj 2588: Spoj 10628. Count on a tree LCA+主席树