整体二分
就是把序列中答案在\([l,mid]\)的划到一个序列中,在\([mid+1,r]\)的划到另一个序列中,再对新生成的序列重复上述操作
容易发现最多只会划分log次
路径\((u,v)\)覆盖路径\((x,y)\)=\(u\)在\(x\)子树中,\(v\)在\(y\)子树中
\(x\)为\(y\)祖先要特殊讨论
这样就可以转成二维偏序
二分答案\(mid\),把权值\(>mid\)都塞进树状数组,套个整体二分就没了
#include <bits/stdc++.h> #define N 40005 #define ll long long #define For(i,x,y) for(int i=(x);i<=(y);++i) #define Rof(i,x,y) for(int i=(x);i>=(y);--i) using namespace std; struct qwq{ int U,V,W; } pl[N]; struct ques{ int x,ly,ry,val,id; } q[N<<2]; struct owo{ int x,y,k,id; }fr[N]; vector<owo> v[N<<2]; vector<ques>pr[N<<2]; vector<int> g[N]; int c[N],d[N],lg[N],dfn[N],low[N],n,PL,FR,dep[N],cnt,tot,f[N][16],ans[N],tmp[N]; bool cmp2(const ques &x,const ques &y){ return x.x<y.x; } bool cmp3(const owo &x,const owo &y){ return x.x<y.x; } void dfs(int x){ dfn[x]=++cnt; For(i,1,lg[dep[x]]) f[x][i]=f[f[x][i-1]][i-1]; for(auto to:g[x]) if(!dfn[to]) dep[to]=dep[x]+1,f[to][0]=x,dfs(to); low[x]=cnt; } int getP(int x,int k){ Rof(i,lg[k],0) if((k>>i)&1) x=f[x][i]; return x; } void add(int l,int r,int val){ for(int i=l;i<=n;i+=(i&(-i))) c[i]+=val; for(int i=r+1;i<=n;i+=(i&(-i))) c[i]-=val; } int qry(int x){ int res=0; for(int i=x;i;i-=(i&(-i))) res+=c[i]; return res; } void solve(int o,int lans,int rans){ if(!v[o].size()) return; if(lans==rans){ for(auto xx:v[o]) ans[xx.id]=d[lans]; v[o].clear(),pr[o].clear(); return; } int mid=(lans+rans)>>1,j=0; For(i,1,FR) tmp[i]=0; For(i,1,n) c[i]=0; For(i,0,(int)pr[o].size()-1){ if(pl[pr[o][i].id].W<=mid){ add(pr[o][i].ly,pr[o][i].ry,pr[o][i].val); pr[o<<1].push_back(pr[o][i]); } else pr[o<<1|1].push_back(pr[o][i]); while(j<(int)v[o].size() && v[o][j].x>=pr[o][i].x && (i==(int)pr[o].size()-1 || v[o][j].x<pr[o][i+1].x)) tmp[v[o][j].id]=qry(v[o][j].y),j++; } for(auto xx:v[o]){ if(tmp[xx.id]>=xx.k) v[o<<1].push_back(xx); else xx.k-=tmp[xx.id],v[o<<1|1].push_back(xx); } v[o].clear(),pr[o].clear(); solve(o<<1,lans,mid); solve(o<<1|1,mid+1,rans); } int main(){ int a,b,w; scanf("%d%d%d",&n,&PL,&FR); For(i,2,n) lg[i]=lg[i>>1]+1; For(i,1,n-1) scanf("%d%d",&a,&b),g[a].push_back(b),g[b].push_back(a); dep[0]=-1,dfs(1); For(i,1,PL) scanf("%d%d%d",&pl[i].U,&pl[i].V,&pl[i].W),d[i]=pl[i].W; sort(d+1,d+PL+1); int sz=unique(d+1,d+PL+1)-d-1; For(i,1,PL) pl[i].W=lower_bound(d+1,d+sz+1,pl[i].W)-d; For(i,1,PL){ if(dfn[pl[i].U]>dfn[pl[i].V]) swap(pl[i].U,pl[i].V); if(dfn[pl[i].V]>=dfn[pl[i].U] && dfn[pl[i].V]<=low[pl[i].U]){ int z=getP(pl[i].V,dep[pl[i].V]-dep[pl[i].U]-1); q[++tot]=(ques){1,dfn[pl[i].V],low[pl[i].V],1,i}; q[++tot]=(ques){dfn[z],dfn[pl[i].V],low[pl[i].V],-1,i}; if(low[z]+1<=n){ q[++tot]=(ques){dfn[pl[i].V],low[z]+1,n,1,i}; q[++tot]=(ques){low[pl[i].V]+1,low[z]+1,n,-1,i}; } } else{ q[++tot]=(ques){dfn[pl[i].U],dfn[pl[i].V],low[pl[i].V],1,i}; q[++tot]=(ques){low[pl[i].U]+1,dfn[pl[i].V],low[pl[i].V],-1,i}; } } q[tot+1].x=n+1; sort(q+1,q+tot+1,cmp2); For(i,1,tot) pr[1].push_back(q[i]); For(i,1,FR){ scanf("%d%d%d",&a,&b,&w); if(dfn[a]>dfn[b]) swap(a,b); fr[i]=(owo){dfn[a],dfn[b],w,i}; } sort(fr+1,fr+FR+1,cmp3); For(i,1,n) v[1].push_back(fr[i]); solve(1,1,sz); For(i,1,FR) printf("%d\n",ans[i]); }