整体二分
就是把序列中答案在\([l,mid]\)的划到一个序列中,在\([mid+1,r]\)的划到另一个序列中,再对新生成的序列重复上述操作
容易发现最多只会划分log次
路径\((u,v)\)覆盖路径\((x,y)\)=\(u\)在\(x\)子树中,\(v\)在\(y\)子树中
\(x\)为\(y\)祖先要特殊讨论
这样就可以转成二维偏序
二分答案\(mid\),把权值\(>mid\)都塞进树状数组,套个整体二分就没了
#include <bits/stdc++.h>
#define N 40005
#define ll long long
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
using namespace std;
struct qwq{ int U,V,W; } pl[N];
struct ques{ int x,ly,ry,val,id; } q[N<<2];
struct owo{ int x,y,k,id; }fr[N];
vector<owo> v[N<<2];
vector<ques>pr[N<<2];
vector<int> g[N];
int c[N],d[N],lg[N],dfn[N],low[N],n,PL,FR,dep[N],cnt,tot,f[N][16],ans[N],tmp[N];
bool cmp2(const ques &x,const ques &y){ return x.x<y.x; }
bool cmp3(const owo &x,const owo &y){ return x.x<y.x; }
void dfs(int x){
dfn[x]=++cnt;
For(i,1,lg[dep[x]]) f[x][i]=f[f[x][i-1]][i-1];
for(auto to:g[x]) if(!dfn[to]) dep[to]=dep[x]+1,f[to][0]=x,dfs(to);
low[x]=cnt;
}
int getP(int x,int k){
Rof(i,lg[k],0) if((k>>i)&1) x=f[x][i];
return x;
}
void add(int l,int r,int val){
for(int i=l;i<=n;i+=(i&(-i))) c[i]+=val;
for(int i=r+1;i<=n;i+=(i&(-i))) c[i]-=val;
}
int qry(int x){
int res=0;
for(int i=x;i;i-=(i&(-i))) res+=c[i];
return res;
}
void solve(int o,int lans,int rans){
if(!v[o].size()) return;
if(lans==rans){
for(auto xx:v[o]) ans[xx.id]=d[lans];
v[o].clear(),pr[o].clear();
return;
}
int mid=(lans+rans)>>1,j=0;
For(i,1,FR) tmp[i]=0;
For(i,1,n) c[i]=0;
For(i,0,(int)pr[o].size()-1){
if(pl[pr[o][i].id].W<=mid){
add(pr[o][i].ly,pr[o][i].ry,pr[o][i].val);
pr[o<<1].push_back(pr[o][i]);
} else pr[o<<1|1].push_back(pr[o][i]);
while(j<(int)v[o].size() && v[o][j].x>=pr[o][i].x && (i==(int)pr[o].size()-1 || v[o][j].x<pr[o][i+1].x))
tmp[v[o][j].id]=qry(v[o][j].y),j++;
}
for(auto xx:v[o]){
if(tmp[xx.id]>=xx.k) v[o<<1].push_back(xx);
else xx.k-=tmp[xx.id],v[o<<1|1].push_back(xx);
}
v[o].clear(),pr[o].clear();
solve(o<<1,lans,mid);
solve(o<<1|1,mid+1,rans);
}
int main(){
int a,b,w;
scanf("%d%d%d",&n,&PL,&FR);
For(i,2,n) lg[i]=lg[i>>1]+1;
For(i,1,n-1) scanf("%d%d",&a,&b),g[a].push_back(b),g[b].push_back(a);
dep[0]=-1,dfs(1);
For(i,1,PL) scanf("%d%d%d",&pl[i].U,&pl[i].V,&pl[i].W),d[i]=pl[i].W;
sort(d+1,d+PL+1); int sz=unique(d+1,d+PL+1)-d-1;
For(i,1,PL) pl[i].W=lower_bound(d+1,d+sz+1,pl[i].W)-d;
For(i,1,PL){
if(dfn[pl[i].U]>dfn[pl[i].V]) swap(pl[i].U,pl[i].V);
if(dfn[pl[i].V]>=dfn[pl[i].U] && dfn[pl[i].V]<=low[pl[i].U]){
int z=getP(pl[i].V,dep[pl[i].V]-dep[pl[i].U]-1);
q[++tot]=(ques){1,dfn[pl[i].V],low[pl[i].V],1,i};
q[++tot]=(ques){dfn[z],dfn[pl[i].V],low[pl[i].V],-1,i};
if(low[z]+1<=n){
q[++tot]=(ques){dfn[pl[i].V],low[z]+1,n,1,i};
q[++tot]=(ques){low[pl[i].V]+1,low[z]+1,n,-1,i};
}
} else{
q[++tot]=(ques){dfn[pl[i].U],dfn[pl[i].V],low[pl[i].V],1,i};
q[++tot]=(ques){low[pl[i].U]+1,dfn[pl[i].V],low[pl[i].V],-1,i};
}
}
q[tot+1].x=n+1;
sort(q+1,q+tot+1,cmp2);
For(i,1,tot) pr[1].push_back(q[i]);
For(i,1,FR){
scanf("%d%d%d",&a,&b,&w);
if(dfn[a]>dfn[b]) swap(a,b);
fr[i]=(owo){dfn[a],dfn[b],w,i};
}
sort(fr+1,fr+FR+1,cmp3);
For(i,1,n) v[1].push_back(fr[i]);
solve(1,1,sz);
For(i,1,FR) printf("%d\n",ans[i]);
}