Link
Difficulty
算法难度6,思维难度7,代码难度7
Description
给你一棵树,给你若干个盘子,每个盘子对应着一条链和一个权值
会掉下来若干个苹果,每个苹果对应着一条链和一个k
盘子可以接苹果当且仅当盘子的路径是苹果的路径的子路径
苹果会选择可以接住它的盘子中的权值第k小的
求每个苹果被哪个盘子接住,输出权值
1 ≤ n , m , q ≤ 4 ∗ 1 0 4 1\le n,m,q\le 4*10^4 1≤n,m,q≤4∗104
Solution
首先权值离散化
然后我们来讨论可以接住苹果的盘子满足什么性质
假设苹果的路径为 ( x , y ) (x,y) (x,y),盘子的路径为 ( x ′ , y ′ ) (x',y') (x′,y′)
(以下我们记 d f n ( x ) , e d ( x ) dfn(x),ed(x) dfn(x),ed(x)分别为 x x x的 d f s dfs dfs序和子树内最后一个点的 d f s dfs dfs序)
-
当 l c a ( x ′ , y ′ ) ≠ x ′ lca(x',y')\ne x' lca(x′,y′)̸=x′和 y ′ y' y′
那么我们发现 x , y x,y x,y只能分别位于 x ′ , y ′ x',y' x′,y′的子树内
即: d f n ( x ′ ) ≤ d f n ( x ) ≤ e d ( x ′ ) , d f n ( y ′ ) ≤ d f n ( y ) ≤ e d ( y ′ ) dfn(x')\le dfn(x)\le ed(x'),dfn(y')\le dfn(y)\le ed(y') dfn(x′)≤dfn(x)≤ed(x′),dfn(y′)≤dfn(y)≤ed(y′)
或: d f n ( x ′ ) ≤ d f n ( y ) ≤ e d ( x ′ ) , d f n ( y ′ ) ≤ d f n ( x ) ≤ e d ( y ′ ) dfn(x')\le dfn(y)\le ed(x'),dfn(y')\le dfn(x)\le ed(y') dfn(x′)≤dfn(y)≤ed(x′),dfn(y′)≤dfn(x)≤ed(y′)
这时你就会发现盘子的限制条件可以分成两个矩形
-
当 l c a ( x ′ , y ′ ) = x ′ lca(x',y')=x' lca(x′,y′)=x′(另一种也一样)
那我们记 ( x ′ , y ′ ) (x',y') (x′,y′)上最靠近 x ′ x' x′的那个点为 z z z的话(也就是深度第二小的点)
那么我们发现 x , y x,y x,y只能一个位于 y ′ y' y′的子树内,另一个在 z z z的子树之外
即: d f n ( y ′ ) ≤ d f n ( x ) ≤ e d ( y ′ ) , 1 ≤ d f n ( y ) < d f n ( z ) dfn(y')\le dfn(x) \le ed(y'),1\le dfn(y)<dfn(z) dfn(y′)≤dfn(x)≤ed(y′),1≤dfn(y)<dfn(z)或 e d ( z ) < d f n ( y ) ≤ n ed(z)<dfn(y) \le n ed(z)<dfn(y)≤n
或: d f n ( y ′ ) ≤ d f n ( y ) ≤ e d ( y ′ ) , 1 ≤ d f n ( x ) < d f n ( z ) dfn(y')\le dfn(y) \le ed(y'),1\le dfn(x)<dfn(z) dfn(y′)≤dfn(y)≤ed(y′),1≤dfn(x)<dfn(z)或 e d ( z ) < d f n ( x ) ≤ n ed(z)<dfn(x) \le n ed(z)<dfn(x)≤n
这时你会发现这东西和上面的差不多,只不过这个是四个矩形而已
这时问题就转换成了给定一堆矩形,还有一堆点,矩形带权,对于每个点求包含它的矩形中第k小的权值
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<vector>
#define LL long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=' ';
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f==1?x:-x;
}
const int N=1e5+5;
int n,m,q,tot,H,Hash[N];
int head[N],to[N],Next[N];
inline void addedge(int x,int y){
to[++tot]=y;
Next[tot]=head[x];
head[x]=tot;
}
int dfn[N],dfn_clock,ed[N],dep[N],st[16][N];
inline void dfs(int x,int fa){
dfn[x]=++dfn_clock;
dep[x]=dep[fa]+1;
st[0][x]=fa;
for(int i=1;i<=15;++i)st[i][x]=st[i-1][st[i-1][x]];
for(int i=head[x];i;i=Next[i]){
int u=to[i];
if(u==fa)continue;
dfs(u,x);
}
ed[x]=dfn_clock;
}
inline int getlca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=15;i>=0;--i)
if(dep[st[i][x]]>=dep[y])
x=st[i][x];
if(x==y)return x;
for(int i=15;i>=0;--i)
if(st[i][x]!=st[i][y])
x=st[i][x],y=st[i][y];
return st[0][x];
}
inline int jump(int x,int y){
for(int i=15;i>=0;--i)
if(dep[st[i][x]]>dep[y])
x=st[i][x];
return x;
}
struct data{
int x,y1,y2,val,id,type;
data(){}
data(int _x,int _y1,int _y2,int _val,int _id,int _type):
x(_x),y1(_y1),y2(_y2),val(_val),id(_id),type(_type){}
inline bool operator < (const data& b) const {
if(x==b.x)return type<b.type;
else return x<b.x;
}
};
vector<data> t;
int a[N];
inline void modify(int x,int v){
while(x<=n){
a[x]+=v;
x+=x&-x;
}
}
inline int query(int x){
int ans=0;
while(x){
ans+=a[x];
x-=x&-x;
}
return ans;
}
int ans[N];
inline void solve(vector<data> &t,int l,int r){
if(l==r){
for(vector<data>::iterator it=t.begin();it!=t.end();++it){
if((*it).type==2)
ans[(*it).id]=Hash[l];
}
return;
}
int mid=(l+r)>>1;
vector<data> ls,rs;
for(vector<data>::iterator it=t.begin();it!=t.end();++it){
data d=*it;
if(d.type==2){
int num=query(d.y1);
if(d.val<=num)ls.push_back(d);
else{
d.val-=num;
rs.push_back(d);
}
}
else{
if(d.val<=mid)ls.push_back(d);
else rs.push_back(d);
if(d.val>mid)continue;
modify(d.y1,d.id);
modify(d.y2+1,-d.id);
}
}
solve(ls,l,mid);
solve(rs,mid+1,r);
}
int main(){
n=read();m=read();q=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
addedge(x,y);addedge(y,x);
}
dfs(1,0);
for(int i=1;i<=m;++i){
int x=read(),y=read(),c=read();
int lca=getlca(x,y);
Hash[++H]=c;
if(lca!=x && lca!=y){
t.push_back(data(dfn[x],dfn[y],ed[y],c,1,1));
t.push_back(data(ed[x],dfn[y],ed[y],c,-1,3));
t.push_back(data(dfn[y],dfn[x],ed[x],c,1,1));
t.push_back(data(ed[y],dfn[x],ed[x],c,-1,3));
}
else{
if(lca==y)swap(x,y);
int z=jump(y,x);
t.push_back(data(1,dfn[y],ed[y],c,1,1));
t.push_back(data(dfn[z]-1,dfn[y],ed[y],c,-1,3));
t.push_back(data(ed[z]+1,dfn[y],ed[y],c,1,1));
t.push_back(data(n,dfn[y],ed[y],c,-1,3));
t.push_back(data(dfn[y],1,dfn[z]-1,c,1,1));
t.push_back(data(dfn[y],ed[z]+1,n,c,1,1));
t.push_back(data(ed[y],1,dfn[z]-1,c,-1,3));
t.push_back(data(ed[y],ed[z]+1,n,c,-1,3));
}
}
for(int i=1;i<=q;++i){
int x=read(),y=read(),c=read();
t.push_back(data(dfn[x],dfn[y],-1,c,i,2));
}
sort(Hash+1,Hash+H+1);
H=unique(Hash+1,Hash+H+1)-Hash-1;
for(vector<data>::iterator it=t.begin();it!=t.end();++it){
if((*it).type!=2)
(*it).val=lower_bound(Hash+1,Hash+H+1,(*it).val)-Hash;
}
sort(t.begin(),t.end());
solve(t,1,H);
for(int i=1;i<=q;++i)printf("%d\n",ans[i]);
return 0;
}