https://www.nowcoder.com/acm/contest/172/C
(sbw大佬太强啦 orz)
先把每一个路径(x,y)分成(x,lca),(y,lca)两个路径,然后就能发现,对于某两个(直上直下的)路径a,b,b的下端点在a的下端点子树中,且b的上端点深度<=a的上端点深度,那么b是覆盖a的。
这样的话,我们做一个dfs序,那么能覆盖某个路径的个数就是(下端点在dfs序对应的那个区间中的、上端点深度小于要覆盖的那个路径)的路径的个数。
而且比较容易发现,我们要求的其实就是dfs序那个区间里的深度第k小的路径。
这样的话,就可以搞一个主席树,以深度为权值,每条路径下端点的dfs序为时间往里加值,每次只要询问对应区间的第k小就可以。
不过要注意的是,我找出来的那个点深度大于我在做的这个点的深度的话,是不合法的,要判掉。
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=200020,logn=22; 6 7 ll rd(){ 8 ll x=0;char c=getchar();int neg=1; 9 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 10 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 11 return x*neg; 12 } 13 14 int N,M,L,Q; 15 int lg[maxn],dep[maxn],fa[maxn][logn]; 16 int egh[maxn],eg[maxn*2][2],ect; 17 int pth[maxn],pt[maxn*2][2],pct; 18 int id[maxn],dfn[maxn][2],tot,lst[maxn]; 19 int ch[maxn*logn*8][2],sum[maxn*logn*8],root[maxn*2],rct; 20 21 inline void adeg(int a,int b){ 22 eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect; 23 } 24 inline void adpt(int a,int d){ 25 pt[++pct][0]=d;pt[pct][1]=pth[a];pth[a]=pct; 26 } 27 28 void dfs(int x){ 29 dfn[x][0]=++tot;id[tot]=x; 30 for(int i=1;fa[x][i-1]&&fa[fa[x][i-1]][i-1];i++){ 31 fa[x][i]=fa[fa[x][i-1]][i-1]; 32 } 33 for(int i=egh[x];i!=-1;i=eg[i][1]){ 34 if(dfn[eg[i][0]][0]) continue; 35 dep[eg[i][0]]=dep[x]+1;fa[eg[i][0]][0]=x; 36 L=max(L,dep[x]+1);dfs(eg[i][0]); 37 }dfn[x][1]=tot; 38 } 39 40 inline int lca(int x,int y){ 41 if(dep[x]<dep[y]) swap(x,y); 42 while(dep[x]>dep[y]){ 43 x=fa[x][lg[dep[x]-dep[y]]]; 44 }if(x==y) return x; 45 for(int i=lg[dep[x]-1];i>=0;i--){ 46 if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 47 }return fa[x][0]; 48 } 49 50 void add(int &rn,int ro,int l,int r,int x){ 51 rn=++rct;sum[rn]=sum[ro]+1; 52 if(l<r){int m=l+r>>1; 53 if(x<=m){ 54 add(ch[rn][0],ch[ro][0],l,m,x);ch[rn][1]=ch[ro][1]; 55 }else{ 56 add(ch[rn][1],ch[ro][1],m+1,r,x);ch[rn][0]=ch[ro][0]; 57 } 58 } 59 } 60 int query(int rn,int ro,int l,int r,int k){ 61 //printf("%d %d %d %d %d %d ",l,r,rn,ro,sum[rn],sum[ro]); 62 if(k>sum[rn]-sum[ro]) return -1; 63 if(l==r) return l; 64 else{ 65 int m=l+r>>1,w=sum[ch[rn][0]]-sum[ch[ro][0]]; 66 if(w>=k) return query(ch[rn][0],ch[ro][0],l,m,k); 67 else return query(ch[rn][1],ch[ro][1],m+1,r,k-w); 68 } 69 } 70 71 inline int solve(int x,int k){ 72 if(!k) return dep[x]-1; 73 int y=query(root[lst[dfn[x][1]]],root[lst[dfn[x][0]-1]],1,L,k); 74 if(y==-1||dep[x]<y) return 0; 75 else return dep[x]-y; 76 } 77 78 int main(){ 79 //freopen("protect.in","r",stdin); 80 int i,j,k; 81 N=rd(),M=rd();memset(egh,-1,sizeof(egh)); 82 for(i=1,j=0,k=2;i<=N+10;i++){ 83 if(i>=k) j++,k<<=1;lg[i]=j; 84 } 85 for(i=1;i<N;i++){ 86 int a=rd(),b=rd(); 87 adeg(a,b);adeg(b,a); 88 }dep[1]=1;dfs(1);memset(pth,-1,sizeof(pth)); 89 for(i=1;i<=M;i++){ 90 int a=rd(),b=rd(); 91 int x=lca(a,b); 92 adpt(a,dep[x]);adpt(b,dep[x]); 93 } 94 for(i=1,k=0;i<=N;i++){ 95 for(j=pth[id[i]];j!=-1;j=pt[j][1]){ 96 ++k;add(root[k],root[k-1],1,L,pt[j][0]); 97 }lst[i]=k; 98 } 99 Q=rd(); 100 for(i=1;i<=Q;i++){ 101 int a=rd(),b=rd(); 102 printf("%d ",solve(a,b)); 103 } 104 return 0; 105 }