G. Path Queries ###K //K

题目链接:https://codeforces.ml/contest/1213/problem/G

题意:给定一棵树,n-1条边, m次询问,每次询问 是有多少对点 的简单路径的边权最大不超过q

思路: 类似kruskal 的思想  从小到大边排序 然后再慢慢加进来,每次加边的过程 是sum[u]*sum[v] 

这样可以做到不重不漏  然后前缀和一下就可以查询了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+10;
 4 const int mod=1e9+7;
 5 #define ll long long
 6 #define pi pair<int,int>
 7 #define fi first
 8 #define sc second
 9 #define pb push_back
10 vector<int>E[maxn];
11 ll pre[maxn];
12 struct ac
13 {
14     int u,v,w;
15     bool operator<(ac a)const
16     {
17         return w<a.w;
18     }
19 };
20 ac a[maxn];
21 int f[maxn],sum[maxn];
22 int find1(int x)
23 {
24     if(x==f[x]) return x;
25     return f[x]=find1(f[x]);
26 }
27 
28 int main()
29 {
30     ios::sync_with_stdio(0);
31     cin.tie(0);
32     int n,m;
33     cin>>n>>m;
34     for(int i=1;i<n;i++)
35     {
36         cin>>a[i].u>>a[i].v>>a[i].w;
37     }
38     for(int i=1;i<=n;i++) f[i]=i,sum[i]=1;
39     sort(a+1,a+n);
40     for(int i=1;i<n;i++)
41     {
42         int u=a[i].u,v=a[i].v,w=a[i].w;
43         u=find1(u),v=find1(v);
44         ll temp=1ll*sum[u]*sum[v];
45         f[u]=v;
46         sum[v]+=sum[u];
47         pre[w]+=temp;
48     }
49 
50     for(int i=1;i<maxn;i++)
51         pre[i]+=pre[i-1];
52     for(int i=0;i<m;i++)
53     {
54         int q;
55         cin>>q;
56         if(i!=0) cout<<" ";
57         cout<<pre[q];
58     }
59 
60 
61 
62 }
View Code

 

利用上一次的答案来更新

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+10;
 4 const int mod=1e9+7;
 5 #define ll long long
 6 #define pi pair<int,int>
 7 #define fi first
 8 #define sc second
 9 #define pb push_back
10 
11 ll ans[maxn];
12 ll sum[maxn];
13 int f[maxn];
14 
15 
16 int find1(int x)
17 {
18     if(x==f[x]) return x;
19     return f[x]=find1(f[x]);
20 }
21 
22 
23 struct ac
24 {
25     int u,v,w;
26     bool operator<(ac a)
27     {
28         return w<a.w;
29     }
30 };
31 ac a[maxn];
32 pi b[maxn];
33 
34 int main()
35 {
36     ios::sync_with_stdio(0);
37     cin.tie(0);
38     int n,m;
39     cin>>n>>m;
40     for(int i=1;i<n;i++)
41     {
42         int u,v,w;
43         cin>>u>>v>>w;
44         a[i]={u,v,w};
45     }
46     for(int i=1;i<=n;i++) f[i]=i,sum[i]=1;
47     sort(a+1,a+n);
48     for(int i=1;i<=m;i++)
49     {
50         cin>>b[i].fi;
51         b[i].sc=i;
52     }
53     sort(b+1,b+1+m);
54     int p=1;
55     ll last=0;
56     for(int i=1;i<=m;i++)
57     {
58         int c=b[i].fi,id=b[i].sc;
59         while(p<=n-1&&a[p].w<=c)
60         {
61             int u=a[p].u,v=a[p].v;
62             p++;
63             int t1=find1(u),t2=find1(v);
64             if(t1==t2) continue;
65             f[t2]=t1;
66             last-=sum[t1]*(sum[t1]-1)/2;
67             last-=sum[t2]*(sum[t2]-1)/2;
68             sum[t1]+=sum[t2];
69             last+=sum[t1]*(sum[t1]-1)/2;
70         }
71         ans[id]=last;
72     }
73     for(int i=1;i<=m;i++) cout<<ans[i]<<" ";
74 
75 
76 
77 }
View Code

 

posted @ 2021-02-21 11:30  canwinfor  阅读(66)  评论(0)    收藏  举报