zoukankan      html  css  js  c++  java
  • 2019浙大宁波理工校赛E 雷顿女士与平衡树(并查集)

    这种题一般都是算贡献,对于这题,我们显然发现,每个点作为最大值肯定是有一定范围的。

    因此我们考虑将点排序,计算每个点作为最大值的答案。

    枚举每个点,之后遍历他的邻边,如果有之前被标记过的点,说明他是最大值,因此用并查集维护后,计算集合乘积即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,int> pll;
    const int N=1e6+10;
    const int mod=1e9+7;
    int p[N],sz[N];
    int h[N],ne[N],e[N],idx;
    int st[N];
    int n;
    struct node{
        int w,id;
    }s[N];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void init(){
        int i;
        for(i=1;i<=n;i++){
            p[i]=i;
            sz[i]=1;
        }
    }
    bool cmp(node a,node b){
        return a.w<b.w;
    }
    int find(int x){
        if(x!=p[x]){
            p[x]=find(p[x]);
        }
        return p[x];
    }
    int main(){
        ios::sync_with_stdio(false);
        int t;
        cin>>t;
        while(t--){
            idx=0;
            cin>>n;
            init();
            int i;
            memset(h,-1,sizeof h);
            memset(st,0,sizeof st);
            for(i=1;i<=n;i++){
                cin>>s[i].w;
                s[i].id=i;
            }
            for(i=1;i<n;i++){
                int a,b;
                cin>>a>>b;
                add(a,b);
                add(b,a);
            }
            sort(s+1,s+1+n,cmp);
            ll ans=0;
            for(i=1;i<=n;i++){
                int tmp=s[i].id;
                st[tmp]=1;
                for(int j=h[tmp];j!=-1;j=ne[j]){
                    int k=e[j];
                    if(st[k]){
                        int pa=find(k);
                        int pb=find(tmp);
                        ans=(ans+1ll*sz[tmp]*sz[pa]%mod*s[i].w)%mod;
                        if(pa!=pb){
                            p[pa]=pb;
                            sz[pb]+=sz[pa];
                        }
                    }
                }
            }
            reverse(s+1,s+1+n);
            memset(st,0,sizeof st);
            ll ans1=0;
            init();
            for(i=1;i<=n;i++){
                int tmp=s[i].id;
                st[tmp]=1;
                for(int j=h[tmp];j!=-1;j=ne[j]){
                    int k=e[j];
                    if(st[k]){
                        int pa=find(k);
                        int pb=find(tmp);
                        ans1=(ans1+1ll*sz[tmp]*sz[pa]%mod*s[i].w)%mod;
                        if(pa!=pb){
                            p[pa]=pb;
                            sz[pb]+=sz[pa];
                        }
                    }
                }
            }
            cout<<(ans-ans1+mod)%mod<<endl;
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    git 获取之前某个版本
    mysql默认查询顺序
    tp5链式查询fetchSql(true)方法
    微信中关闭网页输入内容时的安全提示
    SourceTree + BeyondCompare 配置 + 使用教程
    SourceTree 免登录跳过初始设置
    git 常规发布流程
    Git常用操作命令
    手动安装phpRedisAdmin
    docker-compose快速搭建lnmp+redis服务器环境
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14002295.html
Copyright © 2011-2022 走看看