风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果。
由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更
加难的版本。首先有一个地图,是一棵由 n 个顶点、n-1 条边组成的树(例如图 1
给出的树包含 8 个顶点、7 条边)。这颗树上有 P 个盘子,每个盘子实际上是一条
路径(例如图 1 中顶点 6 到顶点 8 的路径),并且每个盘子还有一个权值。第 i 个
盘子就是顶点a_i到顶点b_i的路径(由于是树,所以从a_i到b_i的路径是唯一的),
权值为c_i。接下来依次会有Q个水果掉下来,每个水果本质上也是一条路径,第
i 个水果是从顶点 u_i 到顶点v_i 的路径。幽香每次需要选择一个盘子去接当前的水
果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径(例如
图1中从 3到7 的路径是从1到8的路径的子路径)。这里规定:从a 到b的路径与
从b到 a的路径是同一条路径。当然为了提高难度,对于第 i 个水果,你需要选择
能接住它的所有盘子中,权值第 k_i 小的那个盘子,每个盘子可重复使用(没有使用次数
的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水
果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗?
第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数。
接下来n-1 行,每行两个数 a、b,表示树上的a和b 之间有一条边。树中顶点
按1到 n标号。 接下来 P 行,每行三个数 a、b、c,表示路径为 a 到 b、权值为 c 的盘子,其
中0≤c≤10^9,a不等于b。
接下来Q行,每行三个数 u、v、k,表示路径为 u到 v的水果,其中 u不等于v,你需要选择第 k小的盘子,
第k 小一定存在。
显然这个盘子能接到的水果(a,b)(假设dfn[a]<dfn[b],下同)满足dfn[u]<=dfn[a]<=last[u] && dfn[v]<=dfn[b]<=last[v]
则这个盘子能接到的水果(a,b)满足( (1<=a<=dfn[w]-1) || (last[w]+1<=a<=n) ) && (dfn[v]<=b<=last[v])
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 #define maxn 80005
7 using namespace std;
8 char ch;
9 bool ok;
10 void read(int &x){
11 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
12 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
13 if (ok) x=-x;
14 }
15 int n,p,q,a,b,u,v,w,val,lca,k,tot,now[maxn],son[maxn<<1],pre[maxn<<1];
16 int idx,dfn[maxn],last[maxn],fa[maxn][17],dep[maxn];
17 void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
18 void dfs(int u){
19 dfn[u]=++idx;
20 for (int i=0;fa[u][i];i++) fa[u][i+1]=fa[fa[u][i]][i];
21 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
22 if (v!=fa[u][0]) fa[v][0]=u,dep[v]=dep[u]+1,dfs(v);
23 last[u]=idx;
24 }
25 void swim(int &u,int d){for (int i=16;d;i--) if (d>=(1<<i)) d-=(1<<i),u=fa[u][i];}
26 int calc_lca(int u,int v){
27 if (dep[u]<dep[v]) swap(u,v);
28 swim(u,dep[u]-dep[v]);
29 if (u==v) return u;
30 for (int i=16;i>=0;i--) if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
31 return fa[u][0];
32 }
33 int cnt;
34 struct Plate{
35 int x,xx,y,yy,val;
36 }plate[maxn];
37 bool cmp1(Plate a,Plate b){return a.val<b.val;}
38 struct Point{
39 int x,y,k,id;
40 }point[maxn],tmpl[maxn],tmpr[maxn];
41 struct bit{
42 #define lowbit(x) ((x)&(-(x)))
43 int v[maxn];
44 void modify(int l,int r,int val){
45 for (int i=l;i<=n;i+=lowbit(i)) v[i]+=val;
46 for (int i=r+1;i<=n;i+=lowbit(i)) v[i]-=val;
47 }
48 int query(int x){
49 int ans=0;
50 for (int i=x;i;i-=lowbit(i)) ans+=v[i];
51 return ans;
52 }
53 }T;
54 struct Event{
55 int x,y,yy,v,id;
56 }event[maxn<<1];
57 bool cmp2(Event a,Event b){
58 if (a.x!=b.x) return a.x<b.x;
59 return a.id<b.id;
60 }
61 int sum[maxn],ans[maxn];
62 void solve(int l,int r,int st,int ed){
63 if (st>ed) return;
64 if (l==r){
65 for (int i=st;i<=ed;i++) ans[point[i].id]=plate[l].val;
66 return;
67 }
68 int m=(l+r)>>1,siz=0;
69 for (int i=l;i<=m;i++){
70 event[++siz]=(Event){plate[i].x,plate[i].y,plate[i].yy,1,0};
71 event[++siz]=(Event){plate[i].xx,plate[i].y,plate[i].yy,-1,n+1};
72 }
73 for (int i=st;i<=ed;i++) event[++siz]=(Event){point[i].x,point[i].y,0,0,i};
74 sort(event+1,event+siz+1,cmp2);
75 for (int i=1;i<=siz;i++) if (st<=event[i].id&&event[i].id<=ed) sum[event[i].id]=T.query(event[i].y);
76 else T.modify(event[i].y,event[i].yy,event[i].v);
77 int a=0,b=0;
78 for (int i=st;i<=ed;i++) if (sum[i]>=point[i].k) tmpl[++a]=point[i];
79 else tmpr[++b]=(Point){point[i].x,point[i].y,point[i].k-sum[i],point[i].id};
80 for (int i=st;i<=st+a-1;i++) point[i]=tmpl[i-st+1];
81 for (int i=st+a;i<=ed;i++) point[i]=tmpr[i-st-a+1];
82 solve(l,m,st,st+a-1),solve(m+1,r,st+a,ed);
83 }
84 int main(){
85 read(n),read(p),read(q);
86 for (int i=1;i<n;i++) read(a),read(b),put(a,b),put(b,a);
87 dfs(1);
88 for (int i=1;i<=p;i++){
89 read(u),read(v),read(val),lca=calc_lca(u,v);
90 if (dfn[u]>dfn[v]) swap(u,v);
91 if (u!=lca) plate[++cnt]=(Plate){dfn[u],last[u],dfn[v],last[v],val};
92 else{
93 w=v,swim(w,dep[v]-dep[u]-1);
94 plate[++cnt]=(Plate){1,dfn[w]-1,dfn[v],last[v],val};
95 if (last[w]+1<=n) plate[++cnt]=(Plate){dfn[v],last[v],last[w]+1,n,val};
96 }
97 }
98 sort(plate+1,plate+cnt+1,cmp1);
99 for (int i=1;i<=q;i++){
100 read(u),read(v),read(k);
101 if (dfn[u]>dfn[v]) swap(u,v);
102 point[i]=(Point){dfn[u],dfn[v],k,i};
103 }
104 solve(1,cnt,1,q);
105 for (int i=1;i<=q;i++) printf("%d\n",ans[i]);
106 return 0;
107 }