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 }
利用上一次的答案来更新
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 }

浙公网安备 33010602011771号