标签:
bzoj2588 Spoj 10628. Count on a tree
题意:
n点树,m个询问求点u到点v路径上第k小的点权。强制在线。n,m≤100000
题解:
用主席树维护某节点到根节点的权值数量sz,建树过程可以由父亲节点递推。询问就用倍增求出lca,然后路径上的sz值就为sz[u]-sz[lca]+sz[v]-sz[fa[lca]]。反思:本弱倍增数组写反了,疯狂reQAQ~
代码:
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 #define maxn 100500 6 using namespace std; 7 8 int f[18][maxn],rt[maxn],dep[maxn],ch[maxn*35][2],sz[maxn*35],v[maxn],id[maxn],n,m,size,last,tot; 9 struct e{int t,n;}; e es[maxn*2]; int ess,g[maxn]; 10 void pe(int f,int t){es[++ess]=(e){t,g[f]}; g[f]=ess; es[++ess]=(e){f,g[t]}; g[t]=ess;} 11 struct abc{int v,id;}; abc abcd[maxn]; bool cmp(abc a,abc b){return a.v<b.v;} 12 inline int read(){ 13 char ch=getchar(); int x=0,f=1; 14 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar(); 15 return f*x; 16 } 17 void build1(int &x,int l,int r){ 18 x=++size; sz[x]=ch[x][0]=ch[x][1]=0; if(l==r)return; 19 int mid=(l+r)>>1; build1(ch[x][0],l,mid); build1(ch[x][1],mid+1,r); 20 } 21 void insert(int &x,int l,int r,int val){ 22 size++; sz[size]=sz[x]+1; ch[size][0]=ch[x][0]; ch[size][1]=ch[x][1]; x=size; if(l==r)return; 23 int mid=(l+r)>>1; if(val<=mid)insert(ch[x][0],l,mid,val); if(val>mid)insert(ch[x][1],mid+1,r,val); 24 } 25 void dfs(int x,int fa){ 26 rt[x]=rt[fa]; insert(rt[x],1,tot,v[x]); 27 for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa){ 28 f[0][es[i].t]=x; dep[es[i].t]=dep[x]+1; dfs(es[i].t,x); 29 } 30 } 31 void build2(){ 32 for(int i=1;(1<<i)<=n;i++)inc(j,1,n)f[i][j]=f[i-1][f[i-1][j]]; 33 } 34 int LCA(int u,int v){ 35 if(dep[u]<dep[v])swap(u,v); int t=dep[u]-dep[v]; 36 for(int i=0;(1<<i)<=n;i++)if(t&(1<<i))u=f[i][u]; 37 for(int i=16;i>=0;i--)if(f[i][u]!=f[i][v])u=f[i][u],v=f[i][v]; 38 return u==v?u:f[0][u]; 39 } 40 int solve(int u,int v,int k){ 41 int lca=LCA(u,v),l=1,r=tot,x1=rt[v],x2=rt[f[0][lca]],x3=rt[u],x4=rt[lca]; 42 while(l<r){ 43 int mid=(l+r)>>1,tmp=sz[ch[x1][0]]-sz[ch[x2][0]]+sz[ch[x3][0]]-sz[ch[x4][0]]; 44 if(tmp>=k) 45 r=mid,x1=ch[x1][0],x2=ch[x2][0],x3=ch[x3][0],x4=ch[x4][0]; 46 else 47 k-=tmp,l=mid+1,x1=ch[x1][1],x2=ch[x2][1],x3=ch[x3][1],x4=ch[x4][1]; 48 } 49 return l; 50 } 51 int main(){ 52 n=read(); m=read(); inc(i,1,n)abcd[i]=(abc){read(),i}; inc(i,1,n-1){int a=read(),b=read(); pe(a,b);} 53 sort(abcd+1,abcd+1+n,cmp); 54 inc(i,1,n){if(i==1||abcd[i].v!=abcd[i-1].v)++tot,id[tot]=abcd[i].v; v[abcd[i].id]=tot;} 55 size=0; build1(rt[0],1,tot); dfs(1,0); build2(); 56 inc(i,1,m){ 57 int u=read()^last,v=read(),k=read(); last=id[solve(u,v,k)]; printf("%d",last); if(i!=m)puts(""); 58 } 59 return 0; 60 }
20160621
bzoj2588 Spoj 10628. Count on a tree
标签:
原文地址:http://www.cnblogs.com/YuanZiming/p/5701067.html