题解:
对边和询问都排序,然后每次把符合当前要求的边都扔并查集里,对于每个询问判断当前并查集里节点数即可。
我很无聊地给并查集加了按秩排序,还开了O2,加了快读,也才170ms,虽然在第一面,然鹅还是没有办法排太前。
上述操作都不做也行
代码:
1 #include<cstdio>
2 #include<algorithm>
3 using namespace std;
4 inline int rd(){
5 int x=0; char c=getchar();
6 while(c<'0'||c>'9')c=getchar();
7 while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
8 return x;
9 }
10 const int maxn=1e5+5,maxq=1e5+5;
11 int N,Q,a,b,c,fa[maxn],dep[maxn],f1,f2,now,cnt[maxn],ans[maxq];
12 struct Edge{ int from,to,dis; }edge[maxn];
13 struct Query_{ int k,x,id; }qry[maxq];
14 inline bool cmp1(const Edge&a,const Edge&b){ return a.dis>b.dis; }
15 inline bool cmp2(const Query_&a,const Query_&b){ return a.k>b.k; }
16 inline int getf(int a){
17 if(fa[a]==a) return a;
18 fa[a]=getf(fa[a]);
19 return fa[a];
20 }
21 int main(){
22 scanf("%d%d",&N,&Q);
23 for(int i=1;i<N;i++){
24 a=rd(); b=rd(); c=rd();
25 edge[i].from=a;
26 edge[i].to=b;
27 edge[i].dis=c;
28 }
29 for(int i=1;i<=Q;i++){
30 a=rd(); b=rd();
31 qry[i].k=a; qry[i].x=b; qry[i].id=i;
32 }
33 sort(edge+1,edge+N,cmp1);
34 sort(qry+1,qry+Q+1,cmp2);
35 for(int i=1;i<=N;i++) fa[i]=i,cnt[i]=1;
36 now=0;
37 for(int i=1;i<=Q;i++){
38 while(now+1<=N-1 && edge[now+1].dis>=qry[i].k){
39 now++;
40 f1=getf(edge[now].from);
41 f2=getf(edge[now].to);
42 if(f1!=f2){
43 if(dep[f1]<dep[f2]){
44 fa[f1]=f2;
45 cnt[f2]+=cnt[f1];
46 }
47 else if(dep[f1]>dep[f2]){
48 fa[f2]=f1;
49 cnt[f1]+=cnt[f2];
50 }
51 else{
52 fa[f1]=f2;
53 dep[f2]++;
54 cnt[f2]+=cnt[f1];
55 }
56 }
57 }
58 ans[qry[i].id]=cnt[getf(qry[i].x)]-1;
59 }
60 for(int i=1;i<=Q;i++) printf("%d\n",ans[i]);
61 return 0;
62 }
知识兔View CodeBy:AlenaNuna