zoukankan      html  css  js  c++  java
  • Bzoj5289:[Hnoi2018]排列

    [HNOI/AHOI2018]排列

    题目看这里

    题解

    %20 搜索枚举全排列
    %40 给好的搜索??随机化一下吧,人品可以的应该能拿到吧。
    %60 距离正解差了一个log?发现是树然后暴力枚举???
    %80 都有这个分数了,为什么不拿100???

    正解:
    很显然的是对于(a[i]),我们直接把(i)(a[i])连一条边
    没有0时,无解,听说还要判环
    n+1个点,n条边,连同==>树。
    然后原题变成:
    给出一棵以 0 为根的有根树,需要为非 0 顶点标号 1∼n ,并且满足父亲比自己先标号。每个节点有点权,树的价值为点权乘标号的和。求树最大的价值。
    一个很显然的贪心就是如果当前节点权值很小,且它的父亲被选取了,那么优先给它标号。

    NaVi_Awson爷这里给出了很好的解释,以下原话照搬

    考虑如果 (u) 有父亲,显然当他的父亲被选之后马上就会选 (u) ,也就是说父子间的编号一定是相邻的。我们可以将 (u) 的答案并在他的父亲中。

    同样的,对于两个不同的“块”,也是如此。

    考虑一个长度为 (l1) 的序列 (A) 和一个长度为 (l_2) 的序列 (B)

    序列前面已经安排好了 (loc) 个。考虑 (AB)(BA) 两种合并后的序列的答案:

    (W_{AB}=sum_{i=1}^{l_1}(i+loc)w_{A_i}+sum_{i=1}^{l_2}(i+loc+l_1)w_{B_i})

    (W_{BA}=sum_{i=1}^{l_2}(i+loc)w_{B_i}+sum_{i=1}^{l_1}(i+loc+l_2)w_{A_i})

    如果 (W_{AB}> W_{BA}Rightarrow frac{sum_{i=1}^{l_1}w_{A_i}}{l_1}<frac{sum_{i=1}^{l_2}w_{B_i}}{l_2})

    也就是平均权值小的放前面答案会更优。

    Code

    但是不吸氧要TLEqwq。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #define ll long long 
    using namespace std;
    const ll N=5e5+5;
    ll n,a[N],fa[N],sz[N];
    ll w[N],flag=1;
    struct node{
    	ll id,vi,sz;
    	node(ll _id=0,ll _vi=0,ll _sz=0){id=_id,vi=_vi,sz=_sz;}
    	bool operator < (const node &b) const {return vi*b.sz>b.vi*sz;}
    };
    priority_queue<node>q;
    ll read(){
    	ll x=0,w=1;char ch=getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*w;
    }
    ll find(ll x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    int main(){
    	n=read();
    	for(ll i=1;i<=n;i++){
    		a[i]=read();if(a[i]==0)flag=0;
    	}if(flag){cout<<"-1"<<endl;return 0;}
    	ll ans=0;ll len=0;
    	for(ll i=1;i<=n;i++){
    		w[i]=read();
    		q.push(node(i,w[i],1));
    		sz[i]=1;ans+=w[i];
    	}
    	for(ll i=0;i<=n;i++)fa[i]=i;
    	while(!q.empty()){
    		node t=q.top();q.pop();
    		if(sz[t.id]!=t.sz)continue;
    		if(find(a[t.id])==0){
    			ans+=len*w[t.id];fa[t.id]=0;len+=t.sz;
    		}
    		else {
    			ll tmp=find(a[t.id]);
    			ans+=w[t.id]*sz[tmp];fa[t.id]=tmp;
    			w[tmp]+=w[t.id];sz[tmp]+=sz[t.id];
    			q.push(node(tmp,w[tmp],sz[tmp]));
    		}
    	}cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    第十四次会议
    第十三次会议
    第十二次会议
    第十一次会议
    第十次会议
    第九次会议
    第八次会议
    第七次会议
    第六次会议
    机器学习
  • 原文地址:https://www.cnblogs.com/hhh1109/p/10388351.html
Copyright © 2011-2022 走看看