【BZOJ5289】[HNOI2018]排列(贪心)

题面

BZOJ

洛谷

题解

这个限制看起来不知道在干什么,其实就是找到所有排列\(p\)中,\(p_k=x\),那么\(k<j\),其中\(a[p_j]=x\)。

也就是对于\(a\)数组的每个数\(a[i]\),它必须放在所有\(a[x]=i\)的前面。

那么对于\(i\)向所有满足\(a[x]=i\)的位置\(x\)连边,表示\(i\)必须放在这些数前面。

如果成环必定无解,如果无环则图是森林。

现在考虑每次从度数为\(0\)的点中选一个出来放在序列后面。

考虑这样一个问题,全局的最小值什么时候被选。

如果最小值入度为\(0\),显然直接被选。否则当它的父亲被选,那么它一定直接被选。

所以可以把最小值和其父亲合并在一起。

那么重复这个操作考虑每个联通块和他的父亲合并。

那么考虑两个块被选择的顺序关系,假设两个块\(a,b\),权值和为\(s_a,s_b\),点数为\(d_a,d_b\),那么:

\(W_{ab}=W_a+W_b+d_a*s_b\),\(W_{ba}=W_b+W_a+d_b*s_a\)。

不难发现如果\(a\)要放在\(b\)前面的话,就要满足\(d_a*s_b>d_b*s_a\)。即先选平均权值较小的块。

那么每次就选出这个块,然后把它和它的父亲合并在一起就好了,产生的贡献是\(d_a*s_b\)。

那么用\(set\)维护这个过程就做完了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<set>
using namespace std;
#define ll long long
#define MAX 500500
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1,tot;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int n,a[MAX],w[MAX],d[MAX];ll ans,W[MAX];
struct data{ll s;int d,r;};set<data> Q;
bool operator<(data a,data b){ll s1=1ll*a.s*b.d,s2=1ll*b.s*a.d;return s1==s2?a.r<b.r:s1<s2;}
int f[MAX];int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
bool vis[MAX];int sz[MAX];
void dfs(int u,int ff)
{
vis[u]=true;sz[u]=1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff)continue;
if(vis[v])puts("-1"),exit(0);
dfs(v,u);sz[u]+=sz[v];
}
}
data Get(int x){return (data){W[x],d[x],x};}
int main()
{
n=read();int pos=0;
for(int i=1;i<=n;++i)Add(a[i]=read(),i),f[i]=i;
for(int i=1;i<=n;++i)w[i]=read();
dfs(0,-1);if(sz[0]!=n+1){puts("-1");return 0;}
Q.insert((data){W[0]=1e18,d[0]=1,0});
for(int i=1;i<=n;++i)Q.insert((data){W[i]=w[i],d[i]=1,i});
while(!Q.empty())
{
data u=*Q.begin();Q.erase(u);if(!u.r)break;
int F=getf(a[u.r]);data v=Get(F);
Q.erase(v);ans+=u.s*v.d;
W[F]+=u.s;d[F]+=u.d;f[getf(u.r)]=F;
Q.insert(Get(F));
}
printf("%lld\n",ans);
return 0;
}

【BZOJ5289】[HNOI2018]排列(贪心)的更多相关文章

  1. BZOJ5289: [Hnoi2018]排列

    传送门 第一步转化,令 \(q[p[i]]=i\),那么题目变成: 有一些 \(q[a[i]]<q[i]\) 的限制,\(q\) 必须为排列,求 \(max(\sum_{i=1}^{n}w[i] ...

  2. [BZOJ5289][HNOI2018]排列(拓扑排序+pb_ds)

    首先确定将所有a[i]向i连边之后会形成一张图,图上每条有向边i->j表示i要在j之前选. 图上的每个拓扑序都对应一种方案(如果有环显然无解),经过一系列推导可以发现贪心策略与合并的块的大小和w ...

  3. BZOJ.5289.[AHOI/HNOI2018]排列(贪心 heap)

    BZOJ LOJ 洛谷 \(Kelin\)写的挺清楚的... 要求如果\(a_{p_j}=p_k\),\(k\lt j\),可以理解为\(k\)要在\(j\)之前选. 那么对于给定的\(a_j=k\) ...

  4. 5289: [Hnoi2018]排列

    5289: [Hnoi2018]排列 链接 分析: 首先将题意转化一下:每个点向a[i]连一条边,构成了一个以0为根节点的树,要求选一个拓扑序,点x是拓扑序中的第i个,那么价值是i*w[x].让价值最 ...

  5. BZOJ5289:[HNOI2018]排列

    我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

  6. bzoj 5289: [Hnoi2018]排列

    Description Solution 首先注意到实际上约束关系构成了一棵树 考虑这个排列 \(p\),编号为 \(a[i]\) 的出现了,\(i\) 才可以出现 那么如果连边 \((a[i],i) ...

  7. [HNOI2018]排列

    Description: 给定 \(n\) 个整数 \(a_1, a_2, \dots, a_n, 0 \le a_i \le n\),以及 \(n\) 个整数 \(w_1, w_2, \dots, ...

  8. [HNOI/AHOI2018]排列 贪心

    题面 题解: 把题面的限制换成中文: 如果排在第k位的下标 = 排在第j位的值 ,那么k < j 换一个描述方式: 一个值为x的数要排在第x个数后面. 再换一个描述方式: \(fa[i] = a ...

  9. loj2509 hnoi2018排列

    题意:对于a数组,求它的一个合法排列的最大权值.合法排列:对于任意j,k,如果a[p[j]]=p[k],那么k<j. 权值:sigma(a[p[i]]*i).n<=50W. 标程: #in ...

随机推荐

  1. 福州大学软件工程1816 | W班 第5次作业成绩排名

    写在前面 汇总成绩排名链接 1.作业链接 第五次作业--项目选题报告(团队) 2.评分准则 本次作业映射总分为100分+贡献度得分,由以下部分组成: 选题报告内容(10分) 本组评审表设计(5分) 现 ...

  2. hadoop和java 配置环境变量的的tar

    第一步:打开工具上传tar包 如下图 第二步:在文件路径下查看是否上传成功 第三步:解压tar包               tar -zxvf hadoop.2.6.5.tar.gz 第四步:配置环 ...

  3. ansible jenkins war

    Ansible is Simple IT Automationhttps://www.ansible.com/ Ansible中文权威指南- 国内最专业的Ansible中文官方学习手册http://a ...

  4. 如何入门vue之二

    学习完指令之后我们需要学习的就是组件. 在学习组件前我们要了解一下 methods 用来处理事件的. computed用来计算属性  他就是类似于data一样只不过是动态的处理数据 里面写的方法当成属 ...

  5. 解决多人开发时使用window.onload的覆盖问题

    通用型小函数:解决多人开发时,同时使用window.onload事件所出现的后面的window.onload函数覆盖前面一个window.onload函数的问题. function addLoadEv ...

  6. AdminLTE 前端框架

    适合运维平台  后台管理系统 AdminLTE 是一个开源的后台控制面板和仪表盘 WebApp 模板. 这是一个快速的HTML模板,基于CSS框架的引导. 文档: http://adminlte.la ...

  7. django mysql数据库使用自己的User

    由于我需要的User模型与django自带的User有所不同,所以需要定义自己的User Model,这里记录一下方法,适用于django 1.5+. 因为使用自己的后台,放弃django的管理后台, ...

  8. sed命令参数之-r -i

    对于初学linux的朋友来说,能记住命令附带的一大帮参数就以及非常不容易了.好不容易把该用的参数都想全了.sed -irns 后面一大片脚本 ,一执行出错了 what!!!! 创建一下测试环境 hea ...

  9. JSON in SQL Server 2016

    JSON functions in SQL Server enable you to analyze and query JSON data, transform JSON to relational ...

  10. Rest模式get,put,post,delete含义与区别

    POST   /uri     创建   DELETE /uri/xxx 删除    PUT    /uri/xxx 更新或创建   GET    /uri/xxx 查看   GET操作是安全的.所谓 ...