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()

    ......

  • 相关阅读:
    EJB>依赖注入(dependency injection) 小强斋
    EJB>自定义安全域 小强斋
    EJB>定时服务(Timer Service) 小强斋
    EJB>依赖注入(dependency injection) 小强斋
    EJB>定时服务(Timer Service) 小强斋
    EJB>安全服务的具体开发 小强斋
    EJB>JMS(Java Message Service)和消息驱动bean 小强斋
    EJB>拦截器(Interceptor) 小强斋
    《做最好的员工》第二章:好员工擅长合作
    教你29招,让你在社交,职场上人人对你刮目相看 !
  • 原文地址:https://www.cnblogs.com/myrtle/p/12046384.html
Copyright © 2011-2022 走看看