题目
表示这种题好套路啊。
原题如果注意到一条路径包含另一条路径,那么在dfs序上第一条路径的端点与第二条路径的端点是有一个偏序关系的。
然后就变成了二分答案+三维偏序。
因为可以离线,
将二分答案和一维整合起来变成整体二分
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
剩下两维就是一个二维偏序,排序后树状数组维护
O
(
log
n
)
O(\log n)
O(logn)。
一共
O
(
n
log
2
n
)
O(n\log ^2n)
O(nlog2n)
AC Code:
#include<bits/stdc++.h>
#define maxn 40005
using namespace std;
int n,P,Q,m;
int sb[maxn];
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e=0;
void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v;}
int st[maxn],ed[maxn],tot,fa[maxn];
void dfs(int now,int ff){
st[now] = ++tot;
fa[now] = ff;
for(int i=info[now];i;i=Prev[i])
if(to[i]!=ff)
dfs(to[i],now);
ed[now] = tot;
}
struct Plate{
int a,b,c;
bool operator <(const Plate &B)const{ return c==B.c?a==B.a?b<B.b:a<B.a:c<B.c; }
}p[maxn];
struct Query{
int u,v,k;
bool operator <(const Query &B)const{ return k==B.k?u==B.u?v<B.v:u<B.u:k<B.k; }
}q[maxn];
struct Modify{
int u,l,r,v,val;
Modify(int u=0,int l=0,int r=0,int v=0,int val=0):u(u),l(l),r(r),v(v),val(val){}
}md[maxn*10];
bool cmp1(const int &u,const int &v){ return md[u].val==md[v].val?md[u].v<md[v].v:md[u].val<md[v].val; }
bool cmp2(const int &u,const int &v){ return md[u].u<md[v].u; }
bool cmp3(const int &u,const int &v){ return q[u].u < q[v].u; }
int cm[maxn*10],cq[maxn],q1[maxn],q2[maxn],ans[maxn];
int tr[maxn];
inline void upd(int now,int val){ for(;now<=n;now+=now&-now) tr[now]+=val; }
inline int qsum(int now,int ret=0){for(;now;now-=now&-now) ret+=tr[now];return ret; }
void Solve(int l,int r,int ml,int mr,int ql,int qr){
if(ml > mr || ql > qr) return;
if(l==r){
for(int i=ql;i<=qr;i++)
ans[cq[i]] = sb[l];
return;
}
int mid = (l+r) >> 1 , cnt = ml;
for(;md[cm[cnt]].val<=mid;cnt++);
sort(cm+ml,cm+cnt,cmp2);
int j = ml , r1 = 0 , r2 = 0;
for(int i=ql;i<=qr;i++){
//printf("%d %d\n",i,q[cq[i]].u);
for(;j<cnt && md[cm[j]].u<=q[cq[i]].u;j++){
upd(md[cm[j]].l,md[cm[j]].v) , upd(md[cm[j]].r+1,-md[cm[j]].v);
}
int tmp;
if((tmp = qsum(q[cq[i]].v)) < q[cq[i]].k)
q2[r2++] = cq[i] , q[cq[i]].k-=tmp;
else q1[r1++] = cq[i];
}
//puts("");
for(int i=ql;i<ql+r1;i++) cq[i]=q1[i-ql];
for(int i=ql+r1;i<=qr;i++) cq[i]=q2[i-ql-r1];
for(j--;j>=ml;j--) upd(md[cm[j]].l,-md[cm[j]].v) , upd(md[cm[j]].r+1,md[cm[j]].v);
sort(cm+ml,cm+mr+1,cmp1);
Solve(l,mid,ml,cnt-1,ql,ql+r1-1),Solve(mid+1,r,cnt,mr,ql+r1,qr);
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d%d%d",&n,&P,&Q);
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Node(u,v),Node(v,u);
dfs(1,0);
for(int i=1;i<=P;i++) scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c),sb[++sb[0]]=p[i].c;
for(int i=1;i<=Q;i++){
scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].k),cq[i]=i;
if(st[q[i].u] > st[q[i].v]) swap(q[i].u,q[i].v);
q[i].u = st[q[i].u] , q[i].v = st[q[i].v];
}
sort(sb+1,sb+1+sb[0]);
sb[0]=unique(sb+1,sb+1+sb[0])-sb-1;
for(int i=1;i<=P;i++) p[i].c = lower_bound(sb+1,sb+1+sb[0],p[i].c)-sb;
for(int i=1;i<=P;i++){
if(st[p[i].a] > st[p[i].b]) swap(p[i].a,p[i].b);
if(ed[p[i].a] < st[p[i].b]){
md[++m] = Modify(st[p[i].a],st[p[i].b],ed[p[i].b],1,p[i].c),cm[m]=m;
md[++m] = Modify(ed[p[i].a]+1,st[p[i].b],ed[p[i].b],-1,p[i].c),cm[m]=m;
}
else{
int j;
for(j=info[p[i].a];j;j=Prev[j])
if(st[to[j]]<=st[p[i].b] && ed[p[i].b]<=ed[to[j]] && to[j]!=fa[p[i].a])
break;
j = to[j];
md[++m] = Modify(1,st[p[i].b],ed[p[i].b],1,p[i].c),cm[m]=m;
md[++m] = Modify(st[j],st[p[i].b],ed[p[i].b],-1,p[i].c),cm[m]=m;
md[++m] = Modify(st[p[i].b],ed[j]+1,n,1,p[i].c),cm[m]=m;
md[++m] = Modify(ed[p[i].b]+1,ed[j]+1,n,-1,p[i].c),cm[m]=m;
}
}
sort(cm+1,cm+1+m,cmp1);
sort(cq+1,cq+1+Q,cmp3);
Solve(1,sb[0],1,m,1,Q);
for(int i=1;i<=Q;i++) printf("%d\n",ans[i]);
}