对于一条路径x-y:
·若x与y成祖先-孩子关系,假设y是x的祖先,z是y到x方向的第一个节点,则包含它的路径满足:起点在x的子树里,且终点不在z的子树里。
·若x与y不成祖先-孩子关系,则包含它的路径满足:起点在x的子树里,且终点在y的子树里。
于是每个盘子可以拆成一个或两个矩形,每个水果可以当成两个点。
整体二分的时候扫描线+树状数组维护,时间复杂度$O(n\log^2n)$。
#include<cstdio>
#include<algorithm>
#define N 40010
using namespace std;
int n,m,Q,i,x,y,z,q[N],tmp[N],now[N],ans[N],T,pos[N],bit[N];
int g[N],nxt[N<<1],v[N<<1],ed,d[N],size[N],son[N],top[N],f[N],st[N],en[N],dfn;
struct E{
int x1,x2,l1,r1,l2,r2,z;
E(){}
E(int _x1,int _x2,int _l1,int _r1,int _l2,int _r2,int _z){
x1=_x1,x2=_x2,l1=_l1,r1=_r1,l2=_l2,r2=_r2,z=_z;
}
}e[N];
inline bool cmp(const E&a,const E&b){return a.z<b.z;}
struct P{int x,y,k,p;P(){}P(int _x,int _y,int _k,int _p){x=_x,y=_y,k=_k,p=_p;}}a[N];
struct B{int x,l,r,t;B(){}B(int _x,int _l,int _r,int _t){x=_x,l=_l,r=_r,t=_t;}}b[N<<1];
inline bool cmpb(const B&a,const B&b){return a.x<b.x;}
struct C{int x,y,p;C(){}C(int _x,int _y,int _p){x=_x,y=_y,p=_p;}}c[N<<1];
inline bool cmpc(const C&a,const C&b){return a.x<b.x;}
inline void addedge(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x){
size[x]=1;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
d[v[i]]=d[f[v[i]]=x]+1;dfs(v[i]);size[x]+=size[v[i]];
if(size[v[i]]>size[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int y){
st[x]=++dfn;top[x]=y;
if(son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
en[x]=dfn;
}
inline int lca2(int x,int y){
int t;
while(top[x]!=top[y])t=top[y],y=f[top[y]];
return x==y?t:son[x];
}
inline void add(int x,int p){for(;x<=n;x+=x&-x)if(pos[x]<T)pos[x]=T,bit[x]=p;else bit[x]+=p;}
inline int ask(int x){int t=0;for(;x;x-=x&-x)if(pos[x]==T)t+=bit[x];return t;}
void solve(int l,int r,int h,int t){
if(h>t)return;
if(l==r){
for(int i=h;i<=t;i++)ans[a[q[i]].p]=e[l].z;
return;
}
int mid=(l+r)>>1,cb=0,cc=0;
for(int i=l;i<=mid;i++){
if(e[i].l1<=e[i].r1){
b[cb++]=B(e[i].x1,e[i].l1,e[i].r1,1);
b[cb++]=B(e[i].x2+1,e[i].l1,e[i].r1,-1);
}
if(e[i].l2<=e[i].r2){
b[cb++]=B(e[i].x1,e[i].l2,e[i].r2,1);
b[cb++]=B(e[i].x2+1,e[i].l2,e[i].r2,-1);
}
}
for(int i=h;i<=t;i++){
c[cc++]=C(a[q[i]].x,a[q[i]].y,i);
c[cc++]=C(a[q[i]].y,a[q[i]].x,i);
now[i]=0;
}
T++,sort(b,b+cb,cmpb),sort(c,c+cc,cmpc);
for(int i=0,j=0;i<cc;i++){
while(j<cb&&b[j].x<=c[i].x)add(b[j].l,b[j].t),add(b[j].r+1,-b[j].t),j++;
now[c[i].p]+=ask(c[i].y);
}
int L=h,R=t;
for(int i=h;i<=t;i++)if(now[i]>=a[q[i]].k)tmp[L++]=q[i];else a[q[i]].k-=now[i],tmp[R--]=q[i];
for(int i=h;i<=t;i++)q[i]=tmp[i];
solve(l,mid,h,R),solve(mid+1,r,R+1,t);
}
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
int main(){
read(n),read(m),read(Q);
for(i=1;i<n;i++)read(x),read(y),addedge(x,y),addedge(y,x);
dfs(1),dfs2(1,1);
for(i=1;i<=m;i++){
read(x),read(y),read(z);
if(d[x]<d[y])swap(x,y);
if(st[y]<=st[x]&&en[x]<=en[y])y=lca2(y,x),e[i]=E(st[x],en[x],1,st[y]-1,en[y]+1,n,z);
else e[i]=E(st[x],en[x],st[y],en[y],1,0,z);
}
sort(e+1,e+m+1,cmp);
for(i=1;i<=Q;i++){
q[i]=i;
read(x),read(y),read(z);
a[i]=P(st[x],st[y],z,i);
}
solve(1,m,1,Q);
for(i=1;i<=Q;i++)printf("%d\n",ans[i]);
return 0;
}
原文:http://www.cnblogs.com/clrs97/p/4792787.html