HDU 5884 Sort(2016年青岛网络赛 G 二分+贪心+小优化)
好题
题意:给你n<=100000个数,每个数范围[0,1000],然后给你一个最大的代价T,每次最多合并k个数成为一个数,代价为k个数的总和。问最后合成1个数的总代价不大于T的最小k
题解:我们首先知道当k越大,总代价会越小,这样我们就找到了单调性,可以二分k看是否满足代价(又见最大值最小化问题)。然后我们贪心寻找固定k的最小代价,可以想到每次取前k个最小的值合并成一个,再放入数组中继续这个操作,直到最后变成一个数,这样我们可以直接使用优先队列模拟。
但是直接做会超时,所以我就YY了一个优化的方法。我们可以看到数字个数虽然很多,但是范围很小(数字很密集),所以我们可以首先使用数组记录每种值的个数,然后合并时使用一个指针无回溯向后寻找。这样很方便,因为每次k个数的和一定不小于最大的那个数(指针的位置),这时我们就可以把这个和放入后面的数组中,保证了指针无回溯。但是数字大了后会很低效,所以我们在这时再使用优先队列就好。
可我就这样一直wa,wa,wa。究其原因就是贪心错了。
给个数据:
5 18
1 2 3 4 5
答案是4,但是直接这样计算答案就不是4。。。
因此还有一个问题就是:每次合并k个数意味着减少(k-1)个数,最后变成1个数意味着总共减少(n-1)个数,而(n-1)%(k-1)不等于0时我们需要首先合并前(n-1)%(k-1)+1个最小的数,接着再合并k个数,这样就不会出现最后合并时少于k个数的情况了。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const double Pi=acos(-1.0);
const int Mod=1e9+;
const int Max=;
int pos[Max],num[Max];
struct node
{
int val;
bool operator<(const node &c)const
{
return val>c.val;
}
};
priority_queue<node> pque;//小顶堆
ll Check(int sma,int mid,int n)//从sma开始到n每次最多合并mid个最小代价
{
ll sum=0ll;
node tem;
while(!pque.empty())
pque.pop();
memset(pos,,sizeof(pos));
for(int i=sma; i<n; ++i)//初始化
{
if(num[i]<(ll)Max)
pos[(int)num[i]]++;
else
{
tem.val=num[i];
pque.push(tem);
}
}
int j=,tmp,tmp2;
n=n-sma;//个数可能变小
while(n>)
{
tmp=mid;
tmp2=;
while(j<Max&&n>&&tmp>)//数组里有
{
if(pos[j]==)//只能在这儿才++
{
++j;
continue;
}
tmp2+=j;
pos[j]--;
n--;
tmp--;
}
while(!pque.empty()&&tmp>&&n>)
{
tmp2+=pque.top().val;
pque.pop();
tmp--;
n--;
}
sum+=tmp2;
if(tmp2>=Max)//数组里存不下
{
tem.val=tmp2;
pque.push(tem);
}
else//可以存在数组里(并且一定存在最后访问的位置及后面)
pos[tmp2]++;
n++;
}
return sum;
}
int Dic(int n,int sma,int big,int m)//最大值最小化问题
{
sort(num,num+n);
int tmp,tmp2,tmp3,mm=m;
while(sma<big)
{
int mid=((sma+big)>>);
tmp=;
m=mm;
if((n-)%(mid-))//**每次合并mid个后有余数,余下的首先合并更优**
{
tmp=(n-)%(mid-)+;
tmp2=;
for(int i=;i<tmp;++i)
{
tmp2+=num[i];
m-=num[i];
}
tmp--;
tmp3=num[tmp];
num[tmp]=tmp2;
}
if(Check(tmp,mid,n)>m)//满足单调性
sma=mid+;
else
big=mid;
if(tmp)//注意num数组要修改回来
num[tmp]=tmp3;
}
return big;
}
int main()
{
int t,n;
ll m;
scanf("%d",&t);
while(t--)
{
scanf("%d %I64d",&n,&m);
for(int i=; i<n; ++i)
scanf("%I64d",&num[i]);
if(n<=)
printf("0\n");
else if(n==)
printf("2\n");
else
printf("%d\n",Dic(n,,n,m));
}
return ;
}
HDU 5884 Sort(2016年青岛网络赛 G 二分+贪心+小优化)的更多相关文章
- HDU 5884 Sort -2016 ICPC 青岛赛区网络赛
题目链接 #include <iostream> #include <math.h> #include <stdio.h> #include<algorith ...
- hdu 5881 Tea (2016 acm 青岛网络赛)
原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5881 Tea Time Limit: 3000/1000 MS (Java/Others) Me ...
- 2016 年青岛网络赛---Sort(k叉哈夫曼)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5884 Problem Description Recently, Bob has just learn ...
- 2016 年青岛网络赛---Family View(AC自动机)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5880 Problem Description Steam is a digital distribut ...
- 2016 年青岛网络赛---Tea
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5881 Problem Description Tea is good. Tea is life. Te ...
- HDU 6215 2017Brute Force Sorting 青岛网络赛 队列加链表模拟
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6215 题意:给你长度为n的数组,定义已经排列过的串为:相邻两项a[i],a[i+1],满足a[i]&l ...
- HDU 5875 Function (2016年大连网络赛 H 线段树+gcd)
很简单的一个题的,结果后台数据有误,自己又太傻卡了3个小时... 题意:给你一串数a再给你一些区间(lef,rig),求出a[lef]%a[lef+1]...%a[rig] 题解:我们可以发现数字a对 ...
- HDU 4004 The Frog's Games(2011年大连网络赛 D 二分+贪心)
其实这个题呢,大白书上面有经典解法 题意是青蛙要跳过长为L的河,河上有n块石头,青蛙最多只能跳m次且只能跳到石头或者对面.问你青蛙可以跳的最远距离的最小值是多大 典型的最大值最小化问题,解法就是贪心 ...
- 2018青岛网络赛G - Couleur 区间上的启发式合并
题意:给出\(a[1...n]\),共\(n\)次操作,每次删除一个位置\(p_i\)(强制在线),此时区间会变为两个分离的区间,求每次操作的最大区间逆序对 首先要知道必要的工具,按权值建立的主席树可 ...
随机推荐
- 160824、ionic添加地图站点
1.基本的地图显示 <!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset= ...
- Shell脚本实现用户数据导入
#输入:固定格式的用户数据user.sql #处理:循环读取user.sql中的每行(每行对应一条用户数据),依次调用curl命令将用户插入BearyChat #输出:执行结果输出到日志文件outlo ...
- 数组中binarySearch 中小小的误区! 用的时候大家要注意点
- 用户画像 销量预测 微观 宏观 bi
w 目前我们没有自己的平台 第三方平台又不会给任何我们想要的数据 没有用户的注册信息 全天候的行为信息 用户画像没法做 针对我们业务的bi做的思路是什么呢 数据中心怎么做销量预测呢 ...
- vs编译程序不能实现,“未能完成操作 未指定的错误”的解决办法
1.先把.vcproj 文件剪切到其他地方 2.打开.sln,报错->点“确定”->再点“确定” 3.把 .vcproj 文件 放回来,在vs2005右边的“解决方案”处右键 重新加载,就 ...
- SpringBoot + Thymeleaf + Validate验证
在开发业务时,不可避免的需要处理一些校验, 如果是写 if-else 这种代码去校验, 那会有一大段这样的代码.不过还好有个校验插件: javax.validation.validation-api ...
- 数据库垂直拆分,水平拆分利器,cobar升级版mycat(转)
原文:数据库垂直拆分,水平拆分利器,cobar升级版mycat 1,关于Mycat Mycat情报 基于阿里的开源cobar ,可以用于生产系统中,目前在做如下的一些改进: 非阻塞IO的实现,相对于目 ...
- Python3.6全栈开发实例[003]
3.检查传入列表的长度,如果大于2,将列表的前两项内容返回给调用者. li = [11,22,33,44,55,66,77,88,99,000,111,222] def func3(lst): if ...
- Insert Buffering
14.5.13.4 Insert Buffering Database applications often insert new rows in the ascending order of the ...
- 转载:阮一峰 理解RESTful架构
转载 http://www.ruanyifeng.com/blog/2011/09/restful.html 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件&q ...