版权声明:随意转载,愿意的话提一句作者就好了 https://blog.csdn.net/stone41123/article/details/84061111
Link
Difficulty
算法难度6,思维难度7,代码难度7
Description
给你一棵树,给你若干个盘子,每个盘子对应着一条链和一个权值
会掉下来若干个苹果,每个苹果对应着一条链和一个k
盘子可以接苹果当且仅当盘子的路径是苹果的路径的子路径
苹果会选择可以接住它的盘子中的权值第k小的
求每个苹果被哪个盘子接住,输出权值
Solution
首先权值离散化
然后我们来讨论可以接住苹果的盘子满足什么性质
假设苹果的路径为 ,盘子的路径为
(以下我们记 分别为 的 序和子树内最后一个点的 序)
-
当 和
那么我们发现 只能分别位于 的子树内
即:
或:
这时你就会发现盘子的限制条件可以分成两个矩形
-
当 (另一种也一样)
那我们记 上最靠近 的那个点为 的话(也就是深度第二小的点)
那么我们发现 只能一个位于 的子树内,另一个在 的子树之外
即: 或
或: 或
这时你会发现这东西和上面的差不多,只不过这个是四个矩形而已
这时问题就转换成了给定一堆矩形,还有一堆点,矩形带权,对于每个点求包含它的矩形中第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;
}