1、codeforces 1213G Path Queries
题意:给你一颗n个点的树,求路径最大边权小于等于某个数(m组)的点对数,n,m<=2e5。
分析:算是一道思维题,想到了联通块计算贡献,不知道怎么处理多组询问,看了题解才知道是先将边权排序,依次加入加入边,不断合并并计算联通块的贡献,注意路径压缩,否则tle。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e6+5;
int n,m,wt[N],f[N],sz[N];
struct nd{
int u,v,w;
}p[N];
bool cmp(nd x,nd y) {
return x.w<y.w;
}
pair<int,int> pr[N];
int fd(int x) {
if(x==f[x]) return x;
return f[x] = fd(f[x]);
}
ll ans[N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) f[i]=i,sz[i]=1;
for(int i=1;i<n;i++) {
int u,v,w;
cin>>p[i].u>>p[i].v>>p[i].w;
}
sort(p+1,p+n,cmp);
for(int i=1;i<=m;i++) {
cin>>wt[i];
pr[i] = {wt[i],i};
}
ll res = 0;
sort(pr+1,pr+1+m);
int i=1;
for(int j=1;i<=m&&j<n;i++) {
while(p[j].w<=pr[i].first&&j<n) {
int x=fd(p[j].u),y=fd(p[j].v);
f[x]=y;
res -= 1LL*sz[x]*(sz[x]-1)/2;
res -= 1LL*sz[y]*(sz[y]-1)/2;
sz[y] += sz[x];
res += 1LL*sz[y]*(sz[y]-1)/2;
j++;
}
ans[pr[i].second] = res;
}
while(i<=m) ans[pr[i].second] = res, i++;
for(int i=1;i<=m;i++) cout<<ans[i]<<" ";
cout<<endl;
return 0;
}