洛谷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,求它们的最长公共子序列. 输入输 ...
随机推荐
- RF实现多次失败重跑结果合并的基础方法和优化方法
实现思路:通过分次执行失败案例重跑,然后通过结果文件合并命令实现多次失败重跑结果文件的合并,并输出合并后的log和report文件: 说明:具体失败案例重跑命令和结果文件合并命令请参考本博客其他相关章 ...
- 阿里云CentOS7挂载SSD云盘的方法
https://bbs.aliyun.com/read/151152.html 阿里云购买的第2块云盘默认是不自动挂载的,需要手动配置挂载上. 1.查看SSD云盘 sudo fdisk -l Disk ...
- windows“启动”对应的路径
C:\Users\huangye\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
- Glide加载图片缓存库出现——You cannot start a load for a destroyed activity
请记住一句话:不要再非主线程里面使用Glide加载图片,如果真的使用了,请把context参数换成getApplicationContext.
- 【Nginx】服务器中HTTP 301跳转到带www的域名的方法
从nginx的官方文档 documentation, 正确的nginx https 301跳转到带www域名方法的方法如下: HTTP 301跳转到带www域名方法 需要两个server段. serv ...
- C#访问SQLServer数据库访问帮助类
SQLServer数据库访问帮助类 这里有一个Mysql帮助类的使用例子可以参考(大同小异) 写了一个Mysql的例子,SQLServer的差不多,一样的 C#简单三层结构设计UI.BLL.DAL 1 ...
- git分支的相关问题
场景:github上准备展示vue打包的项目,做预览的功能,首先创建了分支,gh-page,然后成功将dist文件上传到了gh-page分支中,但是,在Settings的时候,发现 并没有gh-pag ...
- router之switch
比较路由中有无switch的区别: 代码一: <Router history={history}> <Route exact path="/" component ...
- Windows Phone Bing lock screen doesn't change解决方法
之前一直用的Lumia 925,Bing lock screen每天都会更换.这几天换了Lumia 930,同步了账号相关的设置,发现Bing lock screen不再每天更换.尝试重启.使用cel ...
- Sublime PlantUML环境配置
参考[http://www.jianshu.com/p/e92a52770832]在安装中遇到不少问题,总结一次成功的步骤如下 一.安装步骤: 1)准备java 环境 jdk1.7 2)安装Subl ...