题目链接:http://codeforces.com/problemset/problem/808/E

题意:给出n个体积为wi, 价值为ci的物品,背包容量为m,求能容纳的最大物品价值,其中 1<=wi<=3;

思路:看到题目首先想到了atcoder的一道题http://www.cnblogs.com/geloutingyu/p/6789985.html

然而这里的 n 为 1e5,直接贪心枚举肯定是不行的.可以考虑O(nlogn)的算法...

这里可以先按照价值从大到小枚举体积为3的物品,用剩余的容量去装体积为1, 和 2 的物品使剩余空间取得最大值,所有枚举情况中的最大值即为答案;

现在问题转化成了在O(longn)的时间复杂度内求出剩余空间能容纳的1,和2物品最大价值,以物品2的数目为 x 轴,能容纳的最大价值为 y 轴,

将其描点再连成光滑曲线后是一条单峰抛物线 / 单峰拋物线的一侧 ;可以做个简易的证明,对于已经降序排列的物品1, 物品2 显然其单位体积的

价值是非递增的,用 i 表示当前选了 i 个物品2,area2( i )为前 i 个物品平均单位体积的价值,显然 area2( i )是随 i 非递增的,物品1同理,并且这里的容量是固定的,

所以其在以物品2的数目为x轴,最大价值为 y 轴的直角坐标系中的图形为:

  1,若物品1, 2的体积和不大于背包剩余空间,则其为单峰函数的左侧;

  2,对于物品1, 2的体积和大于背包剩余空间,有:

    a,若area2(index2) > area1(1),其中index2为物品2的数目,则其为单峰函数左侧;

    b,若area2(1) < area1(index1),其中index1为物品1的数目,则其为单峰函数右侧;

    c,其他情况则存在峰;

对于单峰函数直接三分一下物品2的数目即可找峰值,注意这里可能会存在单调的情况(为单峰函数的一侧),所以还要判断一下边界;

ps:我试了下先枚举物品3再三分物品1的数目wa了,百思不得其解,望路过的大佬指教~

代码:

 #include <iostream>
#include <stdio.h>
#include <algorithm>
#define ll long long
using namespace std; const int MAXN = 3e5+;
ll a[MAXN], b[MAXN], c[MAXN];
ll va[MAXN], vb[MAXN], vc[MAXN];
int n, m, indxa=, indxb=, indxc=; bool cmp(ll a, ll b){
return a > b;
} void get_v(void){
for(int i=; i<=m; i++){
va[i] = va[i-] + a[i];
}
for(int i=; i*<=m; i++){
vb[i<<] = vb[(i-)<<] + b[i];
vb[(i<<)-] = vb[(i-)<<];
}
for(int i=; i*<=m; i++){
vc[i*] = vc[(i-)*] + c[i];
}
} ll f(int x, int w){
if(x* > w) x=w>>;
return vb[x*] + va[w-x*];
} ll find(int w){//三分体积为2的数目
if(w <= ) return ;
int l=, r=w, rmid=w, lmid=;
while(l < r-){
lmid = l+(r-l)/;
rmid = r-(r-l)/;
if(f(lmid, w) > f(rmid, w)) r = rmid;
else l = lmid;
}
return max(max(max(max(f(l, w), f(r, w)), f(lmid, w)), f(rmid, w)), f(, w));//***注意这里的边界条件
} int main(void){
ll ans=;
scanf("%d%d", &n, &m);
for(int i=; i<n; i++){
int x, y;
scanf("%d%d", &x, &y);
if(x == ) a[indxa++] = y;
else if(x == ) b[indxb++] = y;
else c[indxc++] = y;
}
sort(a+, a+indxa, cmp);
sort(b+, b+indxb, cmp);
sort(c+, c+indxc, cmp);
get_v();
for(int i=; i*<=m; i++){//枚举体积为3的数目
ll cnt = vc[i*];
cnt += find(m-i*);
ans = ans > cnt ? ans : cnt;
}
printf("%lld\n", ans);
return ;
}

cf808E(三分)的更多相关文章

  1. hdu3714 三分找最值

    Error Curves Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  2. BZOJ 1857 传送带 (三分套三分)

    在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段.两条传送带分别为线段AB和线段CD.lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R.现在lxhgww想从 ...

  3. hdu 4717(三分求极值)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4717 思路:三分时间求极小值. #include <iostream> #include ...

  4. HDU2438 数学+三分

    Turn the corner Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  5. 三分之一的程序猿之社交类app踩过的那些坑

    三分之一的程序猿之社交类app踩过的那些坑 万众创新,全民创业.哪怕去年陌生人社交不管融资与否都倒闭了不知道多少家,但是依然有很多陌生人社交应用层出不穷的冒出来.各种脑洞大开,让人拍案叫起. 下面我们 ...

  6. 基于jPlayer的三分屏制作

    三分屏,这里的三分屏只是在一个播放器里同时播放三个视频,但是要求只有一个控制面板同时控制它们,要求它们共享一个时间轨道.这次只是简单的模拟了一下功能,并没有深入的研究. 首先,需要下载jPlayer, ...

  7. 【BZOJ-1857】传送带 三分套三分

    1857: [Scoi2010]传送带 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 1077  Solved: 575[Submit][Status][ ...

  8. ACM : HDU 2899 Strange fuction 解题报告 -二分、三分

    Strange fuction Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...

  9. bzoj1857: [Scoi2010]传送带--三分套三分

    三分套三分模板 貌似只要是单峰函数就可以用三分求解 #include<stdio.h> #include<string.h> #include<algorithm> ...

随机推荐

  1. Java for LeetCode 117 Populating Next Right Pointers in Each Node II

    Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...

  2. 序列化组件(get/put/delete接口设计),视图优化组件

    一 . 知识点回顾 1 . 混入类 , 多继承 class Animal(object): def eat(self): print("Eat") def walk(self): ...

  3. Spark与缓存

    预期成果 1.1   当前问题 当前以图搜图应用存在的问题: 当前使用spark RDD方案无法达到数据实时加载(每10分钟加载一次,虽然可配,但太短可能会有问题) Spark RDD内存会被分为两部 ...

  4. AppStore App申请审核加速

    容芳志大牛一直是我学习的榜样 分类: iOS开发经验技巧2014-11-12 09:40 409人阅读 评论(0) 收藏 举报 有没有遇到上线后发现很严重的bug这种情况,修复bug后提交审核又是漫长 ...

  5. 从mediaserver入手快速理解binder机制(最简单理解binder)【转】

    本文转载自;https://blog.csdn.net/u010164190/article/details/53015194 Android的binder机制提供一种进程间通信的方法,使一个进程可以 ...

  6. Java_正则_00_资源贴

    二.参考资料 1.揭开正则表达式的神秘面纱

  7. Java的访问权限修饰符

    default或者friendly表示默认的访问权限修饰符.

  8. leetcode 23. Merge k Sorted Lists(堆||分治法)

    Merge k sorted linked lists and return it as one sorted list. 题意:把k个已经排好序的链表整合到一个链表中,并且这个链表是排了序的. 题解 ...

  9. cmder的下载和使用

    下载地址:http://cmder.net/ 设置环境变量,CMDER_HOME=cmder.exe所在目录,并在path中增加%CMDER_HOME%. 右击我的电脑->属性->(左侧) ...

  10. 「UVA644」 Immediate Decodability(Trie

    题意翻译 本题有多组数据.每组数据给出一列以"9"结尾的仅包含'0'和'1'的字符串,如果里面有一个是另一个的子串,输出"Set &case is not imm ...