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\)(强制在线),此时区间会变为两个分离的区间,求每次操作的最大区间逆序对 首先要知道必要的工具,按权值建立的主席树可 ...
随机推荐
- Android无线测试之—UiAutomator UiSelector API介绍之八
对象搜索—特殊属性.节点与资源ID 一.特殊属性定位对象相关API 返回值 API 描述 UiSelector checkableboolean val) 是否可选择,一般开关组件上具有checkab ...
- sql duplicate key
本文来自:高爽,转载请注明. 向数据库插入记录时,有时会有这种需求,当符合某种条件的数据存在时,去修改它,不存在时,则新增,也就是saveOrUpdate操作.这种控制可以放在业务层,也可以放在数据库 ...
- 【BZOJ4898】[Apio2017]商旅 分数规划+SPFA
[BZOJ4898][Apio2017]商旅 Description 在广阔的澳大利亚内陆地区长途跋涉后,你孤身一人带着一个背包来到了科巴.你被这个城市发达而美丽的市场所深深吸引,决定定居于此,做一个 ...
- idea 不能编译生成class文件
问题:开发工程中将idea中编译输出目录 out 删掉.发现再次编译不能生成class文件 解决方案:settings -> compiler 勾选自动编译选项
- 检验指定路径的文件是否存在ftp服务器中
import org.apache.commons.net.ftp.FTP;import org.apache.commons.net.ftp.FTPClient;import org.apache. ...
- 巨蟒python全栈开发linux之centos4
1.linux虚拟环境1-4 2.linux运行crm代码
- 内置函数:sorted 用法
内置函数——sorted 对list.dict进行排序,Python提供了两个方法 对给定的List L进行排序,方法1: 用List的成员函数sort进行排序,在本地进行排序,不返回副本方法2: ...
- javascript实例:两种方式实现tab栏选项卡
方法1: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...
- app开发制作会难吗?app开发好学吗?
前面我们讲到了app是什么,APP是运行在智能手机的第三方应用程序,可以满足用户的不同需求.那么app开发制作会难吗?这个与产品的复杂度有很大的关系,复杂度包括业务逻辑多不多,业务模块多不多等,对于玩 ...
- (扫盲)WebSocket 教程
原文地址:http://www.ruanyifeng.com/blog/2017/05/websocket.html WebSocket 是一种网络通信协议,很多高级功能都需要它. 本文介绍 WebS ...