Link:
A:
对于不同的$k$,发现限制就是小于$k$的边不能走
那么此时的答案就是由大于等于$k$的边形成的图中$v$所在的连通块除去$v$的大小
为了优化建图过程,考虑离线,将询问和边都按权值从大到小排序,依次加边即可
维护连通性和连通块大小用并查集
#include <bits/stdc++.h> using namespace std; #define X first #define Y second typedef long long ll; typedef pair<int,int> P; typedef double db; const int MAXN=1e5+10; struct query{int k,v,id;}qry[MAXN]; struct edge{int x,y,r;}e[MAXN<<2]; int n,q,f[MAXN],sz[MAXN],res[MAXN]; bool cmp1(edge a,edge b){return a.r>b.r;} bool cmp2(query a,query b){return a.k>b.k;} int find(int x){return f[x]==x?x:f[x]=find(f[x]);} void merge(int x,int y) { int px=find(x),py=find(y); if(px==py) return; f[px]=py;sz[py]+=sz[px]; } int main() { scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) f[i]=i,sz[i]=1; for(int i=1;i<n;i++) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].r); for(int i=1;i<=q;i++) scanf("%d%d",&qry[i].k,&qry[i].v),qry[i].id=i; sort(e+1,e+n,cmp1);sort(qry+1,qry+q+1,cmp2); int top=1; for(int i=1;i<=q;i++) { while(e[top].r>=qry[i].k&&top<n) merge(e[top].x,e[top].y),top++; res[qry[i].id]=sz[find(qry[i].v)]-1; } for(int i=1;i<=q;i++) printf("%d\n",res[i]); return 0; }