洛谷P4437 排列 [HNOI/AHOI2018] 贪心
正解:贪心
解题报告:
发现做题龟速,,,所以懒得写题目大意辣自己$get$一下$QAQ$
首先看到$ai\leq n$,又当$a_{i}=j$时$j$在$i$的前面,所以就变成对于每个点$i$有一个约束,即要求第$a_i$个节点排在$i$的前面
考虑连边,对于$a_i$排在$i$的前面就从$a_i$向i连一条边就好
然后就变成,对于一个点i,一定有一条引向自己的边(但是当$a_{i}=0$的时候就相当于是麻油的),然后每次只能从$x$的前驱走向$x$
仔细一想这样构出来的要么是颗树要么是个环嘛(环就是麻油$a_{i}=0$嘛),如果是个环,那就是无解,最轻松,美滋滋打个-1就可以$return\ 0$了,就很爽
那如果是棵树,就变成辣这样子:有一棵树,一定要先选父亲节点再拓展到儿子节点,求那个式子$max$
(昂我想了下,,,如果有多个$a_{i}=0$其实是个森林,,,?不要在意这种细节反正麻油什么区别的$QwQ$
然后考虑,把所有节点从大到小排序,考虑加入序列
如果它麻油父亲,欧克,直接加进去,继续考虑下一个结点就好
如果它有父亲,那就要先选它父亲,由贪心可知选了它父亲之后选出来的第一个点一定就是点x,所以最终序列中一定是长这样儿的:...,$fa_{x}$,$x$,...
那么像我上面港有父亲的情况下,就相当于把这个节点和父亲节点合并成了一个元素,继续参与节点从大到小排序考虑加入的过程欸
那合并成一个元素之后怎么计算它的权值呢
考虑现在有两个元素,分别代表两个序列$A$,$B$,长度分别为$cnt_a$,$cnt_b$,权值和分别为$sum_a$,$sum_b$(这里的权值和指的是按照那个形式的,$1\cdot A_{1}+2\cdot A_{2}+3\cdot A_{3}$...这样子的$w$),序列和分别为$s_a$,$s_b$(这里的序列和指的是真的$A_1+A_2+A_3+A_4$这样儿的$w$
如果A优于B,就是说A放在B的后面的贡献要大一些,就可以列式:
$sum_b+sum_a+s_a\cdot cnt_b>sum_a+sum_b+s_b\cdot cnt_a$
整理得 $s_a/cnt_a>s_b/cnt_b$
所以可以得到对于一个元素,它的权值就是它的序列中所有点的权值的平均值
然后就做完辣!一直这么做下去就好!over!
再说下,实现的话可以考虑用堆,因为要改变权值所以用$pb$_$ds$中的待修改堆,$set$也成,然后还可以用堆+打标记(这个可以看$psj$的博客,,,他好像是用的优先队列+打标记?麻油仔细看$QAQ$
好神仙啊我天,,,
然后最后说下卡常
一个是不要无脑开$int$
一个是无脑加$rg$
然后最好是手写堆,快两三倍
没了
然后尝试用$set$然后发现太难打了所以代码咕了$QAQ$
然后好不容易打完辣$T$了两个点$QAQ$
然后我卡常卡了一天才过$QAQ$
我$jio$得我还是要学下手写堆和$pb$_$ds$,,,
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define rg register
#define ll int
#define llll long long
#define gc getchar()
#define rp(i,x,y) for(rg ll i=x;i<=y;++i)
#define my(i,x,y) for(rg ll i=x;i>=y;--i)
#define e(x) for(rg ll i=head[x];i;i=edge[i].nxt)
#define t(i) edge[i].to const ll N=+;
ll n,ed_cnt,a[N],head[N],fa[N],sz[N],gg;
llll as,w[N];
bool vis[N];
struct ed{ll to,nxt;}edge[N];
struct dat{ll pos,lth;llll sum;};
set<dat>Q; il ll read()
{
rg char ch=gc;rg ll x=;rg bool y=;
while(ch!='-' && (ch<'' || ch>''))ch=gc;
if(ch=='-')ch=gc,y=;
while(''<=ch && ch<='')x=(x<<)+(x<<)+(ch^''),ch=gc;
return y?x:-x;
}
il bool operator < (rg dat x,rg dat y){rg llll tmp1=(llll)x.sum*y.lth,tmp2=(llll)y.sum*x.lth;return tmp1==tmp2?x.pos<y.pos:tmp1<tmp2;}
il void ad(rg ll x,rg ll y){edge[++ed_cnt]=(ed){y,head[x]};head[x]=ed_cnt;}
void dfs(rg ll x){vis[x]=;++gg;e(x){if(vis[t(i)])printf("-1\n"),exit();dfs(t(i));}}
il ll fd(rg ll x){return fa[x]==x?x:fa[x]=fd(fa[x]);}
il dat cal(rg ll x){return (dat){x,sz[x],w[x]};} int main()
{
// freopen("pl.in","r",stdin);freopen("pl.out","w",stdout);
n=read();rp(i,,n)ad(a[i]=read(),i);dfs();if(gg!=n+)return printf("-1"),;
rp(i,,n)Q.insert((dat){i,sz[i]=,w[i]=read()}),fa[i]=i;Q.insert((dat){,sz[]=,w[]=1e18});
while(!Q.empty())
{
// printf("QAQ\n");
dat tmp=*Q.begin();Q.erase(tmp);if(!tmp.pos)return printf("%lld\n",as),;ll fat=fd(a[tmp.pos]);dat fadat=cal(fat);Q.erase(fadat);
as+=tmp.sum*fadat.lth;w[fat]+=tmp.sum;sz[fat]+=tmp.lth;fa[fd(tmp.pos)]=fat;
Q.insert(cal(fat));
}
printf("%lld\n",as);
return ;
}
所以我还是放下跑不跑得过看运气的代码QAQ,,,
洛谷P4437 排列 [HNOI/AHOI2018] 贪心的更多相关文章
- 【洛谷 P4437】 [HNOI/AHOI2018]排列(贪心,堆)
题目链接 如果\(j<=k,a_{p[j]}!=p[k]\)可以理解为如果\(a_{p[j]}=p[k]\),那么\(k\)一定要放在\(j\)前面,也就是\(a_j\)在\(j\)前面. 于是 ...
- BZOJ5289 & 洛谷4437:[HNOI/AHOI2018]排列——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5289 https://www.luogu.org/problemnew/show/P4437 考虑 ...
- 洛谷P4436 游戏 [HNOI/AHOI2018]
正解:拓扑排序 解题报告: 传送门! 首先不难想到可以把麻油锁的一段先直接缩成一个点,然后预处理每个点能到达的最左和最右节点,然后就能O(1)地查询辣 所以难点在于预处理 可以想到,对于它给定的关于锁 ...
- 洛谷P4425 转盘 [HNOI/AHOI2018] 线段树+单调栈
正解:线段树+单调栈 解题报告: 传送门! 1551又是一道灵巧连题意都麻油看懂的题,,,,所以先解释一下题意好了,,,, 给定一个n元环 可以从0时刻开始从任一位置出发 每次可以选择向前走一步或者在 ...
- 洛谷P4426 毒瘤 [HNOI/AHOI2018] 虚树+树上dp
正解:虚树+树上dp 解题报告: 传送门! 首先解释一下题意趴,,,语文70pts选手已经开始看不懂题辣QAQ 大概就是个给一个图,求独立集方案,且保证图是联通的,边的数量最多只比点多10 首先思考如 ...
- 洛谷P4438 道路 [HNOI/AHOI2018] 树形dp
正解:树形dp 解题报告: 传送门! 昂首先看懂题目趴QwQ大概就是说有棵满二叉树,有n个叶子节点(乡村)和n-1个非叶子节点,然后这棵树的每个节点有三个属性abc,对每个非叶子节点可以从与子节点的两 ...
- BZOJ5290 & 洛谷4438:[HNOI/AHOI2018]道路——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5290 https://www.luogu.org/problemnew/show/P4438 的确 ...
- 【洛谷4424】[HNOI/AHOI2018] 寻宝游戏(位运算思维题)
点此看题面 大致题意: 给你\(n\)个\(m\)位二进制数.每组询问给你一个\(m\)位二进制数,要求你从\(0\)开始,依次对于这\(n\)个数进行\(and\)或\(or\)操作,问有多少种方案 ...
- 洛谷1439 排列LCS问题
洛谷1439 排列LCS问题 本题地址:http://www.luogu.org/problem/show?pid=1439 题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输 ...
随机推荐
- Splash 对象方法
go() wait() jsfunc() evaljs() runjs() autoload() call_later() http_get() http_post() set_content() h ...
- JavaWeb学习总结(十七)EL表达式
语法格式: ${expression} 1. 表达式支持算术运算符合逻辑运算符 <%@ page language="java" contentType="text ...
- 在iOS中使用icon font
博文转载至 http://www.cocoachina.com/industry/20131111/7327.html 在开发阿里数据iOS版客户端的时候,由于项目进度很紧,项目里的所有图标都是用最平 ...
- iOS - UITabBarController中的坑
当你创建一个继承与UITabBarController的子类 并想给其自定义构造方法 传一些值的时候这时候问题出现了: 在创建的时候里面的init方法回调用了 viewdidload,导致每次传值的时 ...
- Linux学习(二)
Linux进程管理 每个 Linux 命令都与系统中的程序对应,输入命令,Linux 就会创建一个新的进程.例如使用 ls 命令遍历目录中的文件时,就创建了一个进程.简而言之,进程就是程序的实例. 创 ...
- [转]F5负载均衡算法及基本原理
原文:Intro to Load Balancing for Developers – The Algorithms 转载:http://blog.gesha.net/archives/205/ p ...
- win10 与linux mint双系统 只能进入mint而无法进入windows的解决方案
新购买了一块ssd,和以前的hdd硬盘一起装双系统:win10和mint ssd:win10 sdb1 sdb2 sdb3 sda2 hdd: mint sda1 ...
- Centos 安装yum,安装ansible
今天使用centos安装ansible,发现域名默认安装是未注册的.提示: This system is not registered to Red Hat Subscription Manageme ...
- 【BZOJ3328】PYXFIB 数论+矩阵乘法
[BZOJ3328]PYXFIB Description Input 第一行一个正整数,表示数据组数据 ,接下来T行每行三个正整数N,K,P Output T行,每行输出一个整数,表示结果 Sampl ...
- Unity3D笔记 GUI 三、实现选项卡二窗口
实现目标: 1.使用个性化Box控件 2.个性化Lable控件 3.添加纵向滚动条 4.新建SelectedItem样式 一.最终效果: 二.主要代码 using UnityEngine; using ...