标签:
按Dfs序逐个插入点,建立可持久化线段树,每次查询即可,具体详见代码。
不知道为什么,代码慢的要死,,
#include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <vector> using namespace std; template<const int _n,const int _m> struct Edge { struct Edge_base { int to,next; }e[_m]; int cnt,p[_n]; Edge() { clear(); } void insert(const int x,const int y) { e[++cnt].to=y; e[cnt].next=p[x]; p[x]=cnt; return ; } int start(const int x) { return p[x]; } void clear() { cnt=1,memset(p,0,sizeof(p)); } Edge_base& operator[](const int x) { return e[x]; } }; Edge<110000,210000> e; vector<int> vec; int n,q,tot,cnt; int a[110000],root[110000],Left[3100000],Right[3100000]; int val[3100000],f[110000][19],depth[110000],lg2[110000]; void Init() { for(int j=1;(1<<j)<=n;++j) for(int i=1;i<=n;++i) f[i][j]=f[f[i][j-1]][j-1]; for(int i=2;i<=n;++i)lg2[i]=lg2[i>>1]+1; return ; } int Lca(int A,int B) { int i,j; if(depth[A]<depth[B])swap(A,B); j=lg2[depth[A]]; for(i=j;i>=0;--i) { if(depth[A]-(1<<i)>=depth[B])A=f[A][i]; } if(A==B)return A; for(i=j;i>=0;--i) { if(f[A][i] && f[A][i]!=f[B][i]) A=f[A][i],B=f[B][i]; } return f[A][0]; } void Insert(const int l,const int r,const int root_l,int& root_r,const int d) { val[root_r=++tot]=val[root_l]+1; if(l==r)return ; int mid=l+((r-l)>>1); if(d<=mid) { Right[root_r]=Right[root_l]; Insert(l,mid,Left[root_l],Left[root_r],d); } else { Left[root_r]=Left[root_l]; Insert(mid+1,r,Right[root_l],Right[root_r],d); } return ; } void Dfs(const int S,const int fa) { depth[S]=depth[fa]+1; f[S][0]=fa; a[S]=lower_bound(vec.begin(),vec.end(),a[S])-vec.begin()+1; Insert(1,vec.size(),root[fa],root[S],a[S]); for(int i=e.start(S);i;i=e[i].next) { if(e[i].to==fa)continue; Dfs(e[i].to,S); } } int kth(int l,int r,int r1,int r2,int r3,int r4,int d) { while(true) { if(l==r)return l; int mid=l+((r-l)>>1),temp; temp=val[Left[r1]]+val[Left[r2]]-val[Left[r3]]-val[Left[r4]]; if(temp>=d)r=mid,r1=Left[r1],r2=Left[r2],r3=Left[r3],r4=Left[r4]; else l=mid+1,r1=Right[r1],r2=Right[r2],r3=Right[r3],r4=Right[r4],d=d-temp; } return 0; } int main() { //freopen("in","r",stdin); int i,x,y,op; vec.resize(110000); scanf("%d%d",&n,&q); for(i=1;i<=n;++i) scanf("%d",&a[i]),vec.push_back(a[i]); sort(vec.begin(),vec.end()); vec.erase(unique(vec.begin(),vec.end()),vec.end()); for(i=1;i<n;++i) { scanf("%d%d",&x,&y); e.insert(x,y); e.insert(y,x); } Dfs(1,0); Init(); for(i=1;i<=q;++i) { scanf("%d%d%d",&op,&x,&y); int temp=Lca(x,y),temp1; if(op==1) temp1=kth(1,vec.size(), root[x],root[y], root[temp],root[f[temp][0]],1); else if(op==2) temp1=kth(1,vec.size(), root[x],root[y], root[temp],root[f[temp][0]], depth[x]+depth[y]-(depth[temp]<<1)+1); else temp1=kth(1,vec.size(), root[x],root[y], root[temp],root[f[temp][0]], ((depth[x]+depth[y]-(depth[temp]<<1)+1)>>1)+1); printf("%d\n",vec[temp1-1]); } return 0; }
[TS-A1505] [清橙2013中国国家集训队第二次作业] 树 [可持久化线段树,求树上路径第k大]
标签:
原文地址:http://www.cnblogs.com/Gster/p/4996922.html