codeforces1213G 경로 분리 된 세트를 조회

문제의 의미

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;
}

추천

출처www.cnblogs.com/xyq0220/p/11729564.html