• [bzoj5289][Hnoi2018]排列【贪心】【堆】


    【题目链接】
      https://www.lydsy.com/JudgeOnline/problem.php?id=5289
      https://www.luogu.org/problemnew/show/P4437
    【题解】
      限制条件可以归纳为:若a[i]要在i之前被选择。
      那么我们将限制关系连边,无解的条件当且仅当出现环。
      否则一定是棵树(因为每个点入度都为1)。
      现在问题转换如下:有一棵树,每个点有权值w[i],现在要再给每个点分配一个不重复的权值p[i],满足p[i]>p[fa[i]]在此基础上最大化i=1np[i]w[i]
      先来考虑一个简单的情况:若w[i]<w[fa[i]]且是w最小的儿子。那么选了fa[i]之后下一个一定会选i。那么我们可以把ifa[i]合并。
      这个结论对于一个连通块也是对的,所以块与块之间也可以比较大小,即比较w的平均值。所以我们可以每次找出权值最小的联通快,将其与他的父亲合并。用并查集+堆即可实现。
      时间复杂度:O(NlogN)
      

    # include <bits/stdc++.h>
    # define    N       500010
    # define    ll      long long
    using namespace std;
    int read(){
        int tmp=0, fh=1; char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
        while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
        return tmp*fh;
    }
    vector <int> p[N];
    struct node{
        int data,next;
    }e[N*2];
    int cnt[N],low[N],dfn[N],head[N],place,use[N],ti,a[N],w[N],n,fa[N],f[N],hp[N],size,id[N];
    ll sum[N],num[N],ans[N];
    bool flag;
    void build(int u, int v){
        e[++place].data=v; e[place].next=head[u]; 
        head[u]=place; cnt[v]++;
    }
    void tarjan(int x){
        use[x]=1; low[x]=dfn[x]=++ti;
        for (int ed=head[x]; ed!=0; ed=e[ed].next){
            if (use[e[ed].data]==2) continue;
            if (use[e[ed].data]==1){
                flag=false; return;
                low[x]=min(low[x],dfn[e[ed].data]);
            }
            else{
                tarjan(e[ed].data);
                low[x]=min(low[x],low[e[ed].data]);
                if (flag==false) return;
            }
        }
    }
    void dfs(int x){
        for (int ed=head[x]; ed!=0; ed=e[ed].next){
            dfs(e[ed].data);
            fa[e[ed].data]=x;
        }
    }
    int dad(int x){
        if (f[x]==x) return x;
            else return f[x]=dad(f[x]);
    }
    bool cmp(int x, int y){
        return sum[x]*1.0/num[x]<sum[y]*1.0/num[y];
    }
    void changeup(int x){
        while (x!=1){
            if (cmp(hp[x],hp[x/2])==true){
                swap(id[hp[x]],id[hp[x/2]]);
                swap(hp[x],hp[x/2]);
                x=x/2;
            }
            else return;
        }
    }
    void changedown(int x){
        int mn;
        while (x*2<=size){
            if (x*2+1<=size&&cmp(hp[x*2+1],hp[x*2])==true)
                mn=x*2+1; else mn=x*2;
            if (cmp(hp[mn],hp[x])==true){
                swap(id[hp[mn]],id[hp[x]]);
                swap(hp[mn],hp[x]);
                x=mn;
            }
            else return;
        }
    }
    int main(){
        n=read();
        for (int i=1; i<=n; i++){
            a[i]=read();
            p[a[i]].push_back(i);
        }
        for (int i=1; i<=n; i++) w[i]=read();
        for (int i=1; i<=n; i++)
            for (unsigned j=0; j<p[i].size(); j++)
                build(i,p[i][j]);
        for (int i=1; i<=n; i++)
            if (cnt[i]==0) build(0,i);
        flag=true;
        tarjan(0);
        if (flag==false||ti!=n+1){
            printf("-1
    ");
            return 0;
        }
        memset(use,0,sizeof(use));
        dfs(0);
        for (int i=1; i<=n; i++){
            num[i]=1, sum[i]=w[i];
            ans[i]=0;
            f[i]=i; id[i]=i;
            hp[++size]=i;
            changeup(i);
        }
        num[0]=1;
        for (int i=1; i<=n; i++){
            int now=hp[1], an=dad(fa[now]);
            swap(id[hp[1]],id[hp[size]]);
            swap(hp[1],hp[size--]);
            changedown(1);
            ans[now]=ans[now]+sum[now]*num[an];
            ans[an]=ans[an]+ans[now];
            num[an]=num[an]+num[now];
            sum[an]=sum[an]+sum[now];
            f[now]=an;
            if (an!=0) changeup(id[an]);
        }
        printf("%lld
    ",ans[0]);
        return 0;
    }
    
  • 相关阅读:
    不容易发现的错误
    Element-UI 笔记
    工作中常用的操作/经验
    记录一些前端强大的插件
    HttpContext.Current.ApplicationInstance.Application vs HttpContext.Current.Application
    What Is a Replay Attack?
    ASP.NET's Data Storage Objects
    JSON Web Token (JWT) RFC7519
    Session-State Modes
    After change SessionID data in Session variables is lost
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9135953.html
Copyright © 2020-2023  润新知