Description
给定一棵n个节点的树,m条带权树上路径(x,y,w),q个询问,求包含给定路径(a,b)的带权路径中权值第k小路径的权值
N,P,Q<=40000。
Solution
现在看啥都是病句了,病句学起来好毒啊
考虑单次询问怎么做。按照dfs序我们把一条路径视作二维平面上的一个点,把盘子能覆盖的路径视作一个或两个矩形,二分答案扫描线做矩形覆盖就行了。
现在多了多组询问,那就整体二分然后就没了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)
#define lowbit(x) (x&-x)
const int N=50005;
struct edge {int y,next;} e[N*2];
struct squr {int x1,y1,x2,y2,x3,y3,w;} t[N];
struct Q {int x,y,k,id;} q[N];
struct line {int x,l,r,v;} ;
int pos[N],dep[N],fa[N],size[N],bl[N];
int ls[N],ans[N],c[N],edCnt;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y) {
e[++edCnt]=(edge) {y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {x,ls[y]}; ls[y]=edCnt;
}
void dfs1(int now) {
size[now]=1;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y==fa[now]) continue;
fa[e[i].y]=now; dep[e[i].y]=dep[now]+1;
dfs1(e[i].y); size[now]+=size[e[i].y];
}
}
void dfs2(int now,int up) {
bl[now]=up; pos[now]=++pos[0];
int mx=0;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y!=fa[now]&&size[e[i].y]>size[mx]) mx=e[i].y;
}
if (!mx) return ;
dfs2(mx,up);
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y!=fa[now]&&e[i].y!=mx) dfs2(e[i].y,e[i].y);
}
}
int get(int x) {
int res=0;
for (;x;x-=lowbit(x)) res+=c[x];
return res;
}
void add(int x,int v) {
for (;x<=pos[0];x+=lowbit(x)) c[x]+=v;
}
void modify(int l,int r,int v) {
add(l,v); add(r+1,-v);
}
bool cmp1(line a,line b) {
return a.x<b.x;
}
bool cmp2(Q a,Q b) {
return a.x<b.x;
}
bool cmp3(squr a,squr b) {
return a.w<b.w;
}
void solve(int l,int r,int tl,int tr) {
if (tl>tr) return ;
if (l==r) {
rep(i,tl,tr) ans[q[i].id]=l;
return ;
}
int mid=(l+r)>>1,rec;
std:: vector <line> u;
std:: vector <Q> v,L,R;
rep(i,l,mid) {
if (t[i].x3<=t[i].y3) {
u.push_back((line) {t[i].x1,t[i].x2,t[i].y2,1});
u.push_back((line) {t[i].y1+1,t[i].x2,t[i].y2,-1});
u.push_back((line) {t[i].x2,t[i].x3,t[i].y3,1});
u.push_back((line) {t[i].y2+1,t[i].x3,t[i].y3,-1});
} else {
u.push_back((line) {t[i].x1,t[i].x2,t[i].y2,1});
u.push_back((line) {t[i].y1+1,t[i].x2,t[i].y2,-1});
}
}
rep(i,tl,tr) v.push_back((Q) {q[i].x,q[i].y,q[i].k,i});
std:: sort(u.begin(), u.end(),cmp1);
std:: sort(v.begin(), v.end(),cmp2);
rep(i,0,pos[0]) c[i]=0;
for (int i=0,j=0;i<v.size();++i) {
for (;j<u.size()&&u[j].x<=v[i].x;++j) {
modify(u[j].l,u[j].r,u[j].v);
}
int res=get(v[i].y);
if (res>=v[i].k) {
L.push_back(q[v[i].id]);
ans[q[v[i].id].id]=mid;
} else {
q[v[i].id].k-=res;
R.push_back(q[v[i].id]);
}
}
rec=L.size();
for (int i=0;i<rec;++i) q[tl+i]=L[i];
for (int i=0;i<R.size();++i) q[tl+rec+i]=R[i];
solve(l,mid,tl,tl+rec-1);
solve(mid+1,r,tl+rec,tr);
}
int get_lca(int x,int y) {
for (;bl[x]!=bl[y];x=fa[bl[x]]) {
if (dep[bl[x]]<dep[bl[y]]) std:: swap(x,y);
}
return dep[x]<dep[y]?x:y;
}
int get_up(int x,int y) {
for (;bl[x]!=bl[y];x=fa[bl[x]]) {
if (dep[bl[x]]<dep[bl[y]]) std:: swap(x,y);
if (fa[x]==y) return x;
if (fa[bl[x]]==y) return bl[x];
}
for (int i=ls[y];i;i=e[i].next) {
if (e[i].y!=fa[y]&&bl[e[i].y]==bl[y]) return e[i].y;
}
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int n=read(),m=read(),C=read();
rep(i,2,n) add_edge(read(),read());
dfs1(dep[1]=1); dfs2(1,1);
rep(i,1,m) {
int x=read(),y=read(),w=read();
if (pos[x]>pos[y]) std:: swap(x,y);
if (get_lca(y,x)==x) {
int z=get_up(y,x);
t[i]=(squr) {1,pos[z]-1,pos[y],pos[y]+size[y]-1,pos[z]+size[z],pos[0],w};
} else t[i]=(squr) {pos[x],pos[x]+size[x]-1,pos[y],pos[y]+size[y]-1,0,-1,w};
}
std:: sort(t+1,t+m+1,cmp3);
rep(i,1,C) {
int x=read(),y=read();
if (pos[x]>pos[y]) std:: swap(x,y);
q[i].x=pos[x],q[i].y=pos[y];
q[i].id=i,q[i].k=read();
}
solve(1,m,1,C);
rep(i,1,C) printf("%d\n", t[ans[i]].w);
return 0;
}