风见幽香非常喜欢玩一个叫做 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 小一定存在。
对于每个果子,输出一行表示选择的盘子的权值。
10 10 10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
3 2 217394434
10 7 13022269
6 7 283254485
6 8 333042360
4 6 442139372
8 3 225045590
10 4 922205209
10 8 808296330
9 2 486331361
4 9 551176338
1 8 5
3 8 3
3 8 4
1 8 3
4 8 1
2 3 1
2 3 1
2 3 1
2 4 1
1 4 1
442139372
333042360
442139372
283254485
283254485
217394434
217394434
217394434
217394434
217394434
N,P,Q<=40000。
考虑一个盘子能接到什么样的水果。
对于一条路径x-y:
若x与y不成祖先-孩子关系,则包含它的路径u-v满足:起点在x的子树里,且终点在y的子树里。
即in[x]<=dfn[u]<=out[x],in[y]<=dfn[v]<=out[y]
若x与y成祖先-孩子关系,假设y是x的祖先,z是y到x方向的第一个节点,则包含它的路径u-v满足:起点在x的子树里,且终点不在z的子树里。
即in[y]<=dfn[u]<=out[u],1<=dfn[v]<=in[z]-1或out[z]+1<=dfn[v]<=n
于是上述条件相当于将每个盘子拆成一个或两个矩形,每个水果可以当成一个点,相当于要求覆盖该点的第k小矩形。
注意中u,v满足的子树区间都是不相交的,所以两种情况作为横坐标的都可以取dfs序较小的那一个,纵坐标取dfs序较大的一个,这样就避免麻烦的讨论了。
接下来上整体二分+扫描线即可。
#include
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=40005,INF=1e9;
int n,m,Q,cnt,ans[N],val[N],bit[N];
int tot,first[N],nxt[N<<1],to[N<<1];
int idx,in[N],out[N],dep[N],fa[N][20];
struct matrix
{
int x1,x2,y1,y2,val;
matrix(){}
matrix(int _x1,int _x2,int _y1,int _y2,int _val):x1(_x1),x2(_x2),y1(_y1),y2(_y2),val(_val){}
}a[N<<1],b[N<<2];
inline bool cmp1(const matrix &a,const matrix &b){return a.valreturn a.x1int x,y,id,k;}q[N],t[N];
inline bool cmp(const node &a,const node &b){return a.xx;}
void add(int x,int y)
{
nxt[++tot]=first[x],first[x]=tot,to[tot]=y;
}
void dfs(int u)
{
in[u]=++idx;
for(int i=1;i<20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int e=first[u];e;e=nxt[e])
{
int v=to[e];
if(v==fa[u][0])continue;
fa[v][0]=u,dep[v]=dep[u]+1;
dfs(v);
}
out[u]=idx;
}
int find(int x,int y)
{
int det=dep[x]-dep[y]-1;
for(int i=0;(1<if(det&(1<x=fa[x][i];
return x;
}
void insert(int x,int v)
{
for(int i=x;i<=n;i+=i&(-i))bit[i]+=v;
}
int query(int x)
{
int res=0;
for(int i=x;i;i-=i&(-i))res+=bit[i];
return res;
}
void calc(int ql,int qr,int vl,int vr)
{
for(int i=ql;i<=qr;i++)val[i]=0;
int l=1,r=cnt,num=0;
while(l<=r)
{
int mid=l+r>>1;
if(a[mid].val1;
else r=mid-1;
}
if(l>cnt)return;
for(int i=l;a[i].val<=vr&&i<=cnt;i++)
{
b[++num]=matrix(a[i].x1,0,a[i].y1,a[i].y2,1);
b[++num]=matrix(a[i].x2+1,0,a[i].y1,a[i].y2,-1);
}
if(!num)return;
sort(b+1,b+num+1,cmp2),sort(q+ql,q+qr+1,cmp);
for(int i=1,j=ql;i<=num||j<=qr;)
{
int x;
if(j>qr)x=b[i].x1;
else if(i>num)x=q[j].x;
else x=min(b[i].x1,q[j].x);
while(i<=num&&b[i].x1==x)
insert(b[i].y1,b[i].val),insert(b[i].y2+1,-b[i].val),i++;
while(j<=qr&&q[j].x<=x)val[j]=query(q[j].y),j++;
}
}
void solve(int ql,int qr,int vl,int vr)
{
if(ql>qr)return;
if(vl==vr)
{
for(int i=ql;i<=qr;i++)ans[q[i].id]=vl;
return;
}
int vmid=(vl+vr)>>1;
calc(ql,qr,vl,vmid);
int st=ql-1;
for(int i=ql;i<=qr;i++)if(q[i].k<=val[i])t[++st]=q[i];
int qmid=st;
for(int i=ql;i<=qr;i++)if(q[i].k>val[i])q[i].k-=val[i],t[++st]=q[i];
for(int i=ql;i<=qr;i++)q[i]=t[i];
solve(ql,qmid,vl,vmid),solve(qmid+1,qr,vmid+1,vr);
}
int main()
{
//freopen("lx.in","r",stdin);
n=getint(),m=getint(),Q=getint();
int x,y,z;
for(int i=1;ix=getint(),y=getint();
add(x,y),add(y,x);
}
dfs(1);
for(int i=1;i<=m;i++)
{
x=getint(),y=getint(),z=getint();
if(in[x]>in[y])swap(x,y);
if(in[x]<=in[y]&&out[y]<=out[x])
{
int w=find(y,x);
if(in[w]>1)a[++cnt]=matrix(1,in[w]-1,in[y],out[y],z);
if(out[w]y],out[y],out[w]+1,n,z);
}
else a[++cnt]=matrix(in[x],out[x],in[y],out[y],z);
}
sort(a+1,a+cnt+1,cmp1);
for(int i=1;i<=Q;i++)
{
x=getint(),y=getint(),z=getint();
if(in[x]>in[y])swap(x,y);
q[i].x=in[x],q[i].y=in[y],q[i].id=i,q[i].k=z;
}
solve(1,Q,0,INF);
for(int i=1;i<=Q;i++)printf("%d\n",ans[i]);
return 0;
}