bzoj2588 Spoj 10628. Count on a tree

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

原文地址:https://www.cnblogs.com/YuanZiming/p/5701067.html