好题

题意:给你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 二分+贪心+小优化)的更多相关文章

  1. HDU 5884 Sort -2016 ICPC 青岛赛区网络赛

    题目链接 #include <iostream> #include <math.h> #include <stdio.h> #include<algorith ...

  2. hdu 5881 Tea (2016 acm 青岛网络赛)

    原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5881 Tea Time Limit: 3000/1000 MS (Java/Others)    Me ...

  3. 2016 年青岛网络赛---Sort(k叉哈夫曼)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5884 Problem Description Recently, Bob has just learn ...

  4. 2016 年青岛网络赛---Family View(AC自动机)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5880 Problem Description Steam is a digital distribut ...

  5. 2016 年青岛网络赛---Tea

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5881 Problem Description Tea is good. Tea is life. Te ...

  6. HDU 6215 2017Brute Force Sorting 青岛网络赛 队列加链表模拟

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6215 题意:给你长度为n的数组,定义已经排列过的串为:相邻两项a[i],a[i+1],满足a[i]&l ...

  7. HDU 5875 Function (2016年大连网络赛 H 线段树+gcd)

    很简单的一个题的,结果后台数据有误,自己又太傻卡了3个小时... 题意:给你一串数a再给你一些区间(lef,rig),求出a[lef]%a[lef+1]...%a[rig] 题解:我们可以发现数字a对 ...

  8. HDU 4004 The Frog's Games(2011年大连网络赛 D 二分+贪心)

    其实这个题呢,大白书上面有经典解法  题意是青蛙要跳过长为L的河,河上有n块石头,青蛙最多只能跳m次且只能跳到石头或者对面.问你青蛙可以跳的最远距离的最小值是多大 典型的最大值最小化问题,解法就是贪心 ...

  9. 2018青岛网络赛G - Couleur 区间上的启发式合并

    题意:给出\(a[1...n]\),共\(n\)次操作,每次删除一个位置\(p_i\)(强制在线),此时区间会变为两个分离的区间,求每次操作的最大区间逆序对 首先要知道必要的工具,按权值建立的主席树可 ...

随机推荐

  1. 转:: 刺鸟:用python来开发webgame服务端(4)

    来源:http://ciniao.me/article.php?id=14 --------------- 刺鸟原创文章,转载请注明出处    前面的工作都已准备就绪,现在我们得来看看服务端怎么和客户 ...

  2. iOS学习笔记(十一)——JSON数据解析

    在之前的<iOS学习——xml数据解析(九)>介绍了xml数据解析,这一篇简单介绍一下Json数据解析.JSON 即 JavaScript Object Natation,它是一种轻量级的 ...

  3. BUFSIZ解析

    BUFSIZ解析: 包含在#include<stdio.h>中,BUFSIZ[=8192]. stdio.h:#ifndef BUFSIZ stdio.h:#define BUFSIZ _ ...

  4. 郭大侠与Rabi-Ribi (优先队列)

    最近郭大侠迷上了玩Rabi-Ribi这个游戏. Rabi-Ribi呢,是一个打兔子的动作冒险游戏,萌萌哒的兔子在地上跑来跑去,好萌好萌呀~ 这个游戏是这样玩的,郭大侠作为一个主角,拿着一个小锤子,他的 ...

  5. EasyNVR支持的摄像机、NVR设备接入类型以及关于国标设备是否支持接入EasyNVR无插件流媒体服务器

    背景分析: 随着互联直播的发展,EasyNVR也是顺应时代潮流顺势发展,也是越来越受广大客户的欢迎. 主要是因为EasyNVR可以完美的摆脱网络的限制,可以实现互联网级别的直播分发和录像回看,特别是对 ...

  6. badboy脚本参数化和检查点

    一.badboy脚本参数化 文本参数化 方式一:直接在Variablesl ist添加参数化变量和值,然后在Script里面找到对应需要参数化的内容-属性,进行替换,参数化名需要用${XX}引用: 方 ...

  7. Python3.6全栈开发实例[007]

    7.此函数只接收一个参数且此参数必须是列表数据类型,此函数完成的功能是返回给调用者一个字典,此字典的键值对为此列表的索引及对应的元素.例如传入的列表为:[11,22,33] 返回的字典为 {0:11, ...

  8. 我的Android进阶之旅------>Android使用百度地图时,关于android.permission.BAIDU_LOCATION_SERVICE的声明警告。

    [重要提醒] 定位SDKv3.1版本之后,以下权限已不需要,请取消声明,否则将由于Android 5.0多帐户系统加强权限管理而导致应用安装失败. <uses-permission androi ...

  9. nginx反向代理三台web

    1.首先我们需要在服务器中三个不同名字,并将他们赋值 2.切换到nginx—conf  把三台机器的nginx的配置文件分别命名为web1.conf.web2.conf.web3.conf vim的赋 ...

  10. locust基本使用

    # coding:utf-8 from locust import HttpLocust,TaskSet,task class BlogDemo(TaskSet): '''用户行为:打开我的博客首页d ...