类似HNOI2017的影魔,思想是把对象映射到平面上。
代码用时:1.5h。非常裸,整体二分加扫描线,树状数组代替线段树既省时有省力。
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=;
int n,m,q,a,b,c,k,u,cnt,fa[N][],dfn[N],tim,lst[N],v[N],dep[N],ans[N],sum[N],nxt[N],h[N],to[N],tot;
struct P{ int x1,x2,y1,y2,v; }p[N];
struct D{ int x,y1,y2,v,id; }d[N];
struct Q{int x,y,k,id; }pnt[N],t1[N],t2[N];
bool operator <(P a,P b){ return a.v<b.v; }
bool operator <(D a,D b){ return a.x==b.x ? a.id<b.id : a.x<b.x; }
void add(int u,int v){ nxt[++tot]=h[u]; h[u]=tot; to[tot]=v; }
int que(int x){ int res=; for (; x; x-=(x&(-x))) res+=v[x]; return res; } void mdf(int l,int r,int k){
for (int i=l; i<=n; i+=(i&(-i))) v[i]+=k;
for (int i=r+; i<=n; i+=(i&(-i))) v[i]-=k;
} void dfs(int x){
dfn[x]=++tim;
rep(i,,) fa[x][i]=fa[fa[x][i-]][i-];
For(i,x) if ((k=to[i])!=fa[x][]) fa[k][]=x,dep[k]=dep[x]+,dfs(k);
lst[x]=tim;
} int go(int a,int h){ for (int i=; ~i; i--) if (h&(<<i)) a=fa[a][i]; return a; } int lca(int a,int b){
if (dep[a]<dep[b]) swap(a,b);
a=go(a,dep[a]-dep[b]);
if (a==b) return a;
for (int i=; ~i; i--) if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i];
return fa[a][];
} void solve(int l,int r,int st,int ed){
if (st>ed) return;
if (l==r){ rep(i,st,ed) ans[pnt[i].id]=p[l].v; return; }
int mid=(l+r)>>,sz=;
rep(i,l,mid){
d[++sz]=(D){p[i].x1,p[i].y1,p[i].y2,,};
d[++sz]=(D){p[i].x2,p[i].y1,p[i].y2,-,n+};
}
rep(i,st,ed) d[++sz]=(D){pnt[i].x,pnt[i].y,,,i};
sort(d+,d+sz+);
rep(i,,sz)
if (st<=d[i].id && d[i].id<=ed) sum[d[i].id]=que(d[i].y1);
else mdf(d[i].y1,d[i].y2,d[i].v);
int a=,b=;
rep(i,st,ed)
if (sum[i]>=pnt[i].k) t1[++a]=pnt[i];
else t2[++b]=(Q){pnt[i].x,pnt[i].y,pnt[i].k-sum[i],pnt[i].id};
rep(i,st,st+a-) pnt[i]=t1[i-st+];
rep(i,st+a,ed) pnt[i]=t2[i-st-a+];
solve(l,mid,st,st+a-); solve(mid+,r,st+a,ed);
} int main(){
freopen("bzoj4009.in","r",stdin);
freopen("bzoj4009.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
rep(i,,n-) scanf("%d%d",&a,&b),add(a,b),add(b,a);
dfs();
rep(i,,m){
scanf("%d%d%d",&a,&b,&c); u=lca(a,b);
if (dfn[a]>dfn[b]) swap(a,b);
if (u!=a) p[++cnt]=(P){dfn[a],lst[a],dfn[b],lst[b],c};
else{
int w=go(b,dep[b]-dep[a]-);
p[++cnt]=(P){,dfn[w]-,dfn[b],lst[b],c};
if (lst[w]<n) p[++cnt]=(P){dfn[b],lst[b],lst[w]+,n,c};
}
}
sort(p+,p+cnt+);
rep(i,,q){
scanf("%d%d%d",&a,&b,&k);
if (dfn[a]>dfn[b]) swap(a,b);
pnt[i]=(Q){dfn[a],dfn[b],k,i};
}
solve(,cnt,,q);
rep(i,,q) printf("%d\n",ans[i]);
return ;
}