zoukankan      html  css  js  c++  java
  • nitacm 2019校赛E雷顿女士与平衡树(并查集维护)

    题目链接:https://ac.nowcoder.com/acm/contest/2995/E

    题意:

    树上从u到v简单路径上所有点权中,最大值与最小值的差值为balance(u,v)。

    T组(T<=10),n(1<=n<=5e5),n个a[i](1<=a[i]<=1e9)表示点权,n-1个u和v,表示u、v两点有边连接,保证构成一棵树

    求树的balance%1e9

    样例:

    答案为179 

    题解:

    最大值与最小值分别计算。

    求最大值的方法:从小到大将每个点与相连的点用并查集合并,同时维护每个联通块的size,此时显然可以计算此点作为最大值的路径条数。

    计算最小值的方法同理。

    思路:

    计算最大值先按点权排序

    点:    4,5,6,8,9,3,10,7,1,2

    点权:2,4,5,5,5,6,  6,8,9,9

    先把点④的vis设为1,表示已访问,然后遍历所有与点④相连的已经访问的点,未找到。

    再把点⑤的vis设为1,表示已经访问,然后遍历所有与点⑤相连的已经访问的点,找到点④,此时需要做如下处理:

    与点④连通的联通块(共有size1个点)的最大点权都为2,与点⑤连通的联通块(共有size2个点)的最大点权都为4,

    从左边联通块任取一点,右边联通块里任取一点,两点之间的最大点权都为4,共有size1*size2对点,再乘上⑤的点权4,即为这一部分的max值

    然后联合两个块,重新计算size(用并查集维护),这个块的点权是多少不重要,因为排序是从小到大,乘的都是大的点的点权。

    计算完所有max点权之和后,按倒序计算min点权,相减即为答案。

    附上代码o(* ̄▽ ̄*)ブ:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5e5+10;
    const int mod=1e9+7;
    int n,fa[maxn],size[maxn],vis[maxn];
    pair<int,int> a[maxn];
    vector<int> G[maxn];
    
    void init()
    {
        for(int i=1;i<=n;i++)fa[i]=i,size[i]=1; 
        memset(vis,0,sizeof vis);
    }
    int get(int x)
    {
        if(fa[x]==x)return x;
        return fa[x]=get(fa[x]);
    }
    void merge(int a,int b)
    {
        a=get(a);
        b=get(b);
        if(a!=b)
        {
            fa[a]=b;
            size[b]+=size[a];
         } 
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            init();
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i].first);
                a[i].second=i;
                G[i].clear(); 
            }
            for(int i=1;i<n;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            sort(a+1,a+1+n);
            long long ans=0;
            for(int i=1;i<=n;i++)
            {
                int now=a[i].second;
                vis[now]=1;
                for(int j:G[now])
                {
                    if(vis[j])
                    {
                        ans=(ans+(1ll*a[i].first*size[now]%mod)*size[get(j)]%mod)%mod;
                        merge(j,now); 
                    }
                }
            }
            
            init();
            for(int i=n;i>=1;i--)
            {
                int now=a[i].second;
                vis[now]=1;
                for(int j:G[now])
                {
                    if(vis[j])
                    {
                        ans=(ans-(1ll*a[i].first*size[now]%mod)*size[get(j)]%mod+mod)%mod;
                        merge(j,now); 
                    }
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    } 

    wa了几发,

    return fa[x]=get(fa[x]);写成return get(fa[x]);

    G[i]没有写clear()

    ......

  • 相关阅读:
    165. Compare Version Numbers
    164. Maximum Gap
    3、桶排序
    162. Find Peak Element
    160. Intersection of Two Linked Lists
    155. Min Stack
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    Linux/Unix系统编程手册 第二章:基本概念
    Linux/Unix系统编程手册 第一章:历史和标准
  • 原文地址:https://www.cnblogs.com/myrtle/p/12046384.html
Copyright © 2011-2022 走看看