【9018:2221】[伪模板]可持久化线段树

2221: [伪模板]可持久化线段树

时间限制: 1 Sec 内存限制: 130 MB
提交: 29 解决: 11
[提交][状态][讨论版]

题目描述

小Z有一棵树,其名曰“可持久化线段树”,这棵树上有n个节点,每个节点有个权值,每1s,每个节点就会长出一个美味度为权值的果子,但是每个节点最多只会有一个果子,现在小Z打算花q秒的时间摘果子,他1s可以摘1个果子,每次摘的果子为两个点最简路径上的美味度第k小的果子,请你回答他的询问。

输入

第1行1个正整数n。

接下来n-1行,每行2个数x,y表示x、y间有边相连;

接下来1行,n个整数,表示每个节点的权值vi;

接下来1行,1个正整数q.

接下来q行,每行3个整数x,y,k表示,这1s,他摘得是x,y最简路径上的第k小。

输出

输出q行,每行1个整数表示答案。

样例输入

8
1 2
1 3
1 4
4 8
2 5
2 6
2 7
3 5 2 4 1 8 3 6
9
5 7 2
6 3 3
7 8 5
3 2 2
2 4 3
1 8 2
1 8 1
1 8 3
2 3 3

样例输出

3
5
6
3
5
4
3
6
5

提示

1<=n,q<=200000 1<=x,y,vi<=n 保证数据合法(是一棵树,且第k小存在)

 题解:树上的主席树,答案为f[fa[lca(x,y)]]+f[lca(x,y)]-f[x]-f[y],注意数值可能重复。

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #define MN 200005
 4 #define MM 5000005
 5 using namespace std;
 6 int n,m,v[MN],ct,h[MN],cnt,ls[MM],rs[MM],T[MM],rt[MM];
 7 int mn=0x7fffffff,mx=-1,dep[MN],fa[MN],sz[MN],son[MN],top[MN];
 8 struct node{int to,nxt;}e[2*MN];
 9 void ins(int u,int v){e[++ct].to=v;e[ct].nxt=h[u];h[u]=ct;}
10 void update(int &k,int l,int r,int ad){
11     ls[++cnt]=ls[k],rs[cnt]=rs[k],T[cnt]=T[k],k=cnt;
12     if(l==r){T[k]++;return;}
13     int mid=(l+r)>>1;
14     if(ad<=mid) update(ls[k],l,mid,ad);
15     else update(rs[k],mid+1,r,ad);
16     T[k]=T[ls[k]]+T[rs[k]];
17 }
18 int que(int k,int l,int r,int qll,int qlr,int qrl,int qrr){
19     if(l==r) return l;
20     int mid=(l+r)>>1;
21     if(k<=T[ls[qrr]]+T[ls[qrl]]-T[ls[qll]]-T[ls[qlr]]) return que(k,l,mid,ls[qll],ls[qlr],ls[qrl],ls[qrr]);
22     else return que(k-=T[ls[qrr]]+T[ls[qrl]]-T[ls[qll]]-T[ls[qlr]],mid+1,r,rs[qll],rs[qlr],rs[qrl],rs[qrr]); 
23 }
24 void dfs1(int u,int f,int d){
25     dep[u]=d,fa[u]=f,sz[u]=1;
26     rt[u]=rt[f],update(rt[u],mn,mx,v[u]);
27     for(int i=h[u];i;i=e[i].nxt)if(e[i].to!=f){
28         dfs1(e[i].to,u,d+1); sz[u]+=sz[e[i].to];
29         if(sz[e[i].to]>sz[son[u]]) son[u]=e[i].to;
30     }
31 }
32 void dfs2(int u,int tp){
33     top[u]=tp; if(son[u]) dfs2(son[u],tp);
34     for(int i=h[u];i;i=e[i].nxt)
35         if(e[i].to!=fa[u]&&e[i].to!=son[u]) dfs2(e[i].to,e[i].to);
36 }
37 int lca(int x,int y){
38     while(top[x]!=top[y])
39         if(dep[top[x]]>dep[top[y]]) x=fa[top[x]];
40         else y=fa[top[y]];
41     return dep[x]>dep[y]?y:x;
42 }
43 int main()
44 {
45     scanf("%d",&n);
46     for(int i=1;i<n;i++){
47         int x,y; scanf("%d%d",&x,&y);
48         ins(x,y); ins(y,x);
49     }
50     for(int i=1;i<=n;i++){
51         scanf("%d",&v[i]);
52         mx=max(mx,v[i]); mn=min(mn,v[i]);
53     }
54     dfs1(1,0,1); dfs2(1,1);
55     scanf("%d",&m);
56     for(int i=1;i<=m;i++){
57         int x,y,z; scanf("%d%d%d",&x,&y,&z);
58         int tmp=lca(x,y);
59         printf("%d
",que(z,mn,mx,rt[fa[tmp]],rt[tmp],rt[x],rt[y]));
60     }
61 }
原文地址:https://www.cnblogs.com/Beginner-/p/8549989.html