luogu P4437 [HNOI / AHOI2018] arrangement

luogu

The essential problem is the \ (a_i \) as \ (i \) father, then if there is not a legitimate ring, or each time you want to take a few, to be met before taking his father have been taken over (0 father directly take), seeking the most value

The idea is to make clear that greedy big weights as far as possible on the back, which is equivalent to the small weight on the front as much as possible so if the minimum number currently no father, apparently taken directly out of the best; and if there is the father, then this number should after its father was taken immediately taken out. then we merge these two points. after repeating this operation to know all the points are taken after completion, will be able to get an answer

There problem is how to take the combined weight of the two points. The combined two points corresponding to two combined sequences, sequences are referred to as \ (\ {a_1, a_2 ... a_n \}, \ {b_1, b_2. ..b_m \} \) , think about when \ (\ {a \} \ ) will be placed \ (\ {b \} \ ) in front, \ (\ {a \} \ ) in the previous answer \ ( ans_a + ans_b + n-\ sum_ {J =. 1} ^ {m} b_j \) , \ (\ {B \} \) in front of the answer to the \ (ans_a + ans_b + m \ sum_ {i = 1} ^ { n-} a_i \) , \ (\ {A \} \) when the front and only if \ (n \ sum_ {j = 1} ^ {m} b_j \ ge m \ sum_ {i = 1} ^ {n} a_i \) , equivalent to \ (\ FRAC {\ SUM n-a_i} {} \ Le \ FRAC {\ b_j SUM {m}} \) , which value is set so that the weight average bit to the right. then two points \ (a, b \) were combined, will produce \ (n \ sum_ {j = 1} ^ {m} b_j \) contributions directly to the answer to Riga

#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double

using namespace std;
const int N=5e5+10;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
struct node
{
    LL w,sz,i;
    bool operator < (const node &bb) const {return w*bb.sz!=bb.w*sz?w*bb.sz>bb.w*sz:i>bb.i;}
    bool operator == (const node &bb) const {return w==bb.w&&sz==bb.sz&&i==bb.i;}
}a[N];
bool ban[N];
struct HEAP
{
    priority_queue<node> q1;
    void mntn(){while(!q1.empty()&&(ban[q1.top().i]||!(q1.top()==a[q1.top().i]))) q1.pop();}
    void push(node x){q1.push(x);}
    void pop(){mntn();q1.pop();}
    node top(){mntn();return q1.top();}
}hp;
int n,fa[N],ff[N];
LL ans,sm;
int findf(int x){return ff[x]==x?x:ff[x]=findf(ff[x]);}

int main()
{
    n=rd();
    for(int i=1;i<=n;++i) ff[i]=i;
    for(int i=1;i<=n;++i)
    {
        fa[i]=rd();
        if(fa[i])
        {
            int x=findf(i),y=findf(fa[i]);
            if(x==y){puts("-1");return 0;}
            ff[y]=x;
        }
    }
    for(int i=1;i<=n;++i)
    {
        int w=rd();
        hp.push((a[i]=(node){w,1,i}));
        sm+=w;
    }
    ans=sm;
    int gg=0;
    for(int i=1;i<=n;++i) ff[i]=i;
    for(int i=1;i<=n;++i)
    {
        int x=hp.top().i;
        hp.pop();
        if(findf(fa[x]))
        {
            int xx=findf(fa[x]);
            ans+=a[xx].sz*a[x].w;
            a[xx].w+=a[x].w,a[xx].sz+=a[x].sz;
            hp.push(a[xx]);
            ff[x]=xx;
        }
        else ff[x]=0,sm-=a[x].w,ans+=a[x].sz*sm;
        ban[x]=1;
    }
    for(int i=1;i<=n;++i) ff[i]=findf(i);
    printf("%lld\n",ans);
    return 0; 
}

Guess you like

Origin www.cnblogs.com/smyjr/p/11563928.html