【贪心】CodeForces Round #140(226B) - Naughty Stone Piles
来源:互联网 发布:火车头采集器数据导出 编辑:程序博客网 时间:2024/04/30 16:34
http://blog.csdn.net/kk303/article/details/8026229
http://blog.csdn.net/zhjchengfeng5/article/details/8023907
http://blog.csdn.net/flying_stones_sure/article/details/8016956
题意:有n(1<=n<=10^5)堆石子,每堆有ai(1<=ai<=10^9)个石子,每次将一堆石子a合并到另一堆b花费为a,求把所有石子合并一起的最小花费。
不过没有那么简单,现在有m(1<=m<=10^5)个询问ki(1<=ki<=10^5),问每堆石子至多被合并ki次,求把所有石子合并在一起的最小花费。
题解:看到数据量显然贪心+乱搞。
首先想ki = 1的情形,不难想到,一堆石子被合并一次,一堆石子被合并一次…一堆石子被合并一次,这显然是让最少的石子去合并别的石子n-1次。
考虑ki = 2,一堆石子被合并二次,二堆石子被合并二次,四堆石子被合并二次…即每次*2。
很好理解,每次可以合并的堆的个数增加了,被合并的堆数也在增加。所以排序后,从大到小贪心即可。同时记录答案。
卡在__int64上居然是re,唉还是考虑不周全10^5不会超int,但是10^5 * 10^5就果断超了唉,比赛可惜了…
Sure原创反省:
想问题的时候不要脱离题目,注意题目的限制条件,画画图,抓住题目的性质,这样就不容易卡题了,再神的题也是出出来做的,总是能够想到方法的,现在自己会的方法已经很多了,还担心刷不了神题?自信点,不要把简单的事情想复杂,要学会思考,不要盯着题目发神。
解题思路:
思想是贪心,至于怎么贪,我们来看看题目给的限制条件:
1、每堆只能被合并 k 次
2、每一堆只能合并一次
注意到这里,我们不难发现,堆与堆之间的关系实际上就构成了一棵树:每个节点表示一个堆,再给个权值(对应堆的重量),每个节点有不多于 k 个子树,合并的过程就是从叶子节点依次向上合并,这样就把题目成功的转化了
接下来就是怎么建树,使得合并产生的花费最少了,根据合并产生花费的方式,不难想到一下两点:
1、 每个节点的子树应该尽量靠近k
2、 距离根的距离越远的层,那一层的权值和应该越小
这样,贪心的策略就出来了
具体实现的时候其实不必建一棵树,我们只需要知道这是一棵树就行了,知道这棵树的第I 层包含哪些节点,这些节点的权值和是多少就完了
这种范围的数据..贪心噜..关键是要逆转思维..从后往前想...
如果没有k的限制条件..显然用最大石头数的堆不动..其他的堆往上加..那么答案是总石头数-最大堆的石头数..
加上k的限制条件.一个石头堆直接移动到最大石头堆中..是1次移动..若其先与其他石头堆合并一次..在同那堆石头一起加到最大石头堆中..实际相当于移动了两次...若其先先合并了k次.. 再加到最大石头堆中..那么这堆移动成功的代价是其石头数*(合并数+1)..为了使得总的代价最小..那么期望的是石头数越大的堆合并的次数越少..
若限制了每堆石头上只能覆盖k堆..对于最大石头堆...其上面的k堆..必然是除了最大石头堆的后k大的堆唯一一次移动...而这k大堆上每个又能容纳k个石头堆.那么就有k^2的堆是移动了两次的...同理..又有k^3个石头堆是移动了3次的...
由此...要求n个石头堆..限制为k时的算法复杂度为 log(k,n)... 但是..要注意k=1的情况..因为不会发生指数增长..所以速度会慢..会超时..但是对于k=1的情况..是可以方便算出来的..特判一下就好了...
#include<iostream>#include<stdio.h>#include<algorithm>#include<string.h>#include<math.h>#include<map>#include<queue>#include<stack>#define ll long long#define oo 2000000000#define pi acos(-1) using namespace std;ll i,n,m,q,a[100005],s[100005],k,p,data,ans;int main(){ while (~scanf("%I64d",&n)) { for (i=1;i<=n;i++) scanf("%I64d",&a[i]); sort(a+1,a+1+n); s[0]=0; for (i=1;i<=n;i++) s[i]=s[i-1]+a[i]; data=0; for (i=n-1;i>=1;i--) data+=a[i]*(n-i); n--; scanf("%I64d",&q); while (q--) { scanf("%I64d",&i); if (i!=1) { p=1; k=i; ans=0; m=n; while (m>=k) { ans+=p*(s[m]-s[m-k]); m-=k; k*=i; p++; } ans+=p*s[m]; }else ans=data; printf("%I64d ",ans); } printf("\n"); } return 0;}
- 【贪心】CodeForces Round #140(226B) - Naughty Stone Piles
- Codeforces 226B Naughty Stone Piles 贪心
- CodeForces Round #140(226B) - Naughty Stone Piles
- Codeforces Round #140 (Div. 1) Naughty Stone Piles 贪心
- Codeforces Round #140 (Div. 1) B Naughty Stone Piles
- #140 (div.1) B. Naughty Stone Piles
- Codeforces Round #202 (Div. 2)B-贪心
- Codeforces Round #305 B题 思维+贪心
- Codeforces Round #274(Div2) B. Towers 贪心
- Codeforces Testing Round #12 B - Restaurant ( 贪心 )
- Codeforces Testing Round #12 B. Restaurant (贪心)
- Educational Codeforces Round 5(B)贪心
- Codeforces Testing Round #12 B. Restaurant (贪心)
- (贪心)Codeforces Round #402 B. Weird Rounding
- Codeforces Round #428 (Div. 2) B 贪心
- Codeforces 387B George and Round(贪心)
- Codeforces Round #109 (Div. 2) B (贪心)
- Codeforces Round #111 (Div. 2) B Unlucky Ticket (贪心)
- asp.net 不可识别的数据库格式,accdb
- HDU2036 改革春风吹满地
- C# 返回父页面
- 关于vs2012/2013的C编译器生成的exe的向后兼容xp的问题
- 日期字符串转时间戳比较
- 【贪心】CodeForces Round #140(226B) - Naughty Stone Piles
- 一元多项式的加法和乘法运算
- 常用算法时间空间复杂度
- java i/o流
- 第八周计算分段函数
- 安卓笔记:解决project explorer中项目旁感叹号
- ZOJ 3826 Hierarchical Notation 模拟
- 自己动手写shell命令之ls
- TextView及其子类