問題の意味
N個のノードのツリーが与えられると、各辺が右縁を有し、m個の問い合わせがあり、各質問\(Q_I \)出力経路ツリーは、右側の点の単純な最大数が超えないいる(\をQ_I \) 。
分析
互いに素セットメンテナンスセットで、サイズを維持しながら。
小から大に縁取らそれぞれを考慮しながら押圧するため、全ての電流経路を流れる電流を描画するエッジの特定の側縁重量であるすべての重量は、図中の各ブロック互いに素なセットメンテナンスユニコムと、最大です。サイズ、現在のエッジを通るパスの数である\(SZ [検索(U)] * SZは、[検索(V)] \) 。プレフィックスとその後をクリックしてください\(O(1)\)尋ねました。
コード
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
#define pb push_back
#define ll long long
using namespace std;
const int inf=1e9;
const int mod=1e9+7;
const int maxn=2e5+10;
int n,m;
int f[maxn];
ll ans[maxn],sz[maxn];
int find(int k){
if(k==f[k]) return k;
else return f[k]=find(f[k]);
}
struct ppo{
int u,v,w;
bool operator<(const ppo &r) const{
return w<r.w;
}
}a[maxn];
int main(){
//ios::sync_with_stdio(false);
//freopen("in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) f[i]=i,sz[i]=1;
for(int i=1;i<n;i++){
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
}
sort(a+1,a+n);
for(int i=1;i<n;i++){
int rx=find(a[i].u),ry=find(a[i].v);
ans[a[i].w]+=sz[rx]*sz[ry];
f[rx]=ry;
sz[ry]+=sz[rx];
}
for(int i=1;i<=2e5;i++) ans[i]+=ans[i-1];
while(m--){
int x;scanf("%d",&x);
printf("%lld ",ans[x]);
}
return 0;
}