洛谷P4095||bzoj3163 [HEOI2013]Eden 的新背包问题
https://www.luogu.org/problemnew/show/P4095
不太会。。
网上有神奇的做法:
第一种其实是暴力(复杂度3e8...)然而可以A。考虑多重背包,发现没有办法快速删除某个物品造成的贡献。考虑对于每个i,求出an1[i]和an2[i],分别表示对于[1,i]和[i,n]区间内所有物品的答案数组(如an1[i][j]表示[1,i]区间内用掉容量j可以带来的最大贡献),这个就是用普通多重背包求出来(可能要优化一下多重背包,以下用了二进制优化)。每次询问(x,y),就暴力枚举在[1,x-1]和[x+1,n]区间内分别取多少容量的物品,取最大贡献。复杂度O(n*log(c)*e+q*e)(如果用二进制优化多重背包)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
int n,n1;
int c[],d[];
int lp[],rp[];
void work(int x,int y,int z)
{
//printf("1t%d %d %d %d\n",x,y,z,k);
++n1;x*=z;y*=z;
c[n1]=x;d[n1]=y;
//printf("1t%d %d\n",c[n1],d[n1]);
}
int qq;
int ans;//int ans[10010];
int an1[][];//an1[i][j]表示(前i个物品)j的容量最大价值
int an2[][];//i及之后的物品...
int main()
{
int i,j,x,y,z;
scanf("%d",&n);
for(i=;i<=n;++i)
{
scanf("%d%d%d",&x,&y,&z);
lp[i]=n1+;
for(j=;(j<<)-<=z;j<<=)
work(x,y,j);
if(z-j+) work(x,y,z-j+);
rp[i]=n1;
}
for(i=;i<=n1;++i)
{
memcpy(an1[i],an1[i-],sizeof(an1[i]));
for(j=;j>=c[i];--j)
an1[i][j]=max(an1[i][j],an1[i][j-c[i]]+d[i]);
}
for(i=n1;i>=;--i)
{
memcpy(an2[i],an2[i+],sizeof(an2[i]));
for(j=;j>=c[i];--j)
an2[i][j]=max(an2[i][j],an2[i][j-c[i]]+d[i]);
}
scanf("%d",&qq);
for(i=;i<=qq;++i)
{
scanf("%d%d",&x,&y);++x;
ans=;
for(j=;j<=y;++j)
ans=max(ans,an1[rp[x-]][j]+an2[lp[x+]][y-j]);
printf("%d\n",ans);
}
return ;
}
第二种是神奇的分治。注意到既不能快速删除多重背包中某个物品造成的贡献,又不能快速合并两个多重背包,但是可以快速向多重背包中加入一个物品。分治时维护一个多重背包的答案数组。solve(l,r),就先把[l,mid]内部的物品加入多重背包,然后solve(mid+1,r),再去掉[l,mid]内部物品造成的贡献(只需要恢复这一步操作之前的贡献数组即可),然后将[mid+1,r]内部的物品加入多重背包,solve(l,mid),去掉[mid+1,r]内部造成的贡献。这样当进行到solve(l,l)时就恰好只有l这个物品自身没有加入多重背包了,此时对于所有对这个位置的询问处理一下即可。复杂度O(n*log(c)*e*log(n)+q)(如果用二进制优化多重背包)(然而以下代码洛谷上跑的比“暴力”慢???)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
int n,n1;
int c[],d[];
int lp[],rp[];
void work(int x,int y,int z)
{
++n1;x*=z;y*=z;
c[n1]=x;d[n1]=y;
}
vector<pii> q[];
int qq;
int an[];int ans[];
void solve(int l,int r)
{
int i,j;
if(l==r)
{
for(i=;i<q[l].size();++i)
ans[q[l][i].se]=an[q[l][i].fi];
return;
}
int mid=l+((r-l)>>);
int an2[];
memcpy(an2,an,sizeof(an2));
for(i=lp[l];i<=rp[mid];++i)
for(j=;j>=c[i];--j)
an[j]=max(an[j],an[j-c[i]]+d[i]);
solve(mid+,r);
memcpy(an,an2,sizeof(an));
for(i=lp[mid+];i<=rp[r];++i)
for(j=;j>=c[i];--j)
an[j]=max(an[j],an[j-c[i]]+d[i]);
solve(l,mid);
memcpy(an,an2,sizeof(an));
}
int main()
{
int i,j,x,y,z;
scanf("%d",&n);
for(i=;i<=n;++i)
{
scanf("%d%d%d",&x,&y,&z);
lp[i]=n1+;
for(j=;(j<<)-<=z;j<<=)
work(x,y,j);
if(z-j+) work(x,y,z-j+);
rp[i]=n1;
}
scanf("%d",&qq);
for(i=;i<=qq;++i)
{
scanf("%d%d",&x,&y);++x;
q[x].pb(pii(y,i));
}
solve(,n);
for(i=;i<=qq;++i)
printf("%d\n",ans[i]);
return ;
}
洛谷P4095||bzoj3163 [HEOI2013]Eden 的新背包问题的更多相关文章
- bzoj3163: [Heoi2013]Eden的新背包问题
Description “寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听.”失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的感觉,却不能回忆起她 ...
- P4095 [HEOI2013]Eden 的新背包问题
P4095 [HEOI2013]Eden 的新背包问题 题解 既然假定第 i 个物品不可以选,那么我们就设置两个数组 dpl[][] 正序选前i个物品,dpr[][] 倒序选前i个物品 ,价格不超过 ...
- BZOJ3163&Codevs1886: [Heoi2013]Eden的新背包问题[分治优化dp]
3163: [Heoi2013]Eden的新背包问题 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 428 Solved: 277[Submit][ ...
- BZOJ 3163: [Heoi2013]Eden的新背包问题( 背包dp )
从左到右, 从右到左分别dp一次, 然后就可以回答询问了. ---------------------------------------------------------- #include< ...
- luogu P4095 [HEOI2013]Eden 的新背包问题 多重背包 背包的合并
LINK:Eden 的新背包问题 就是一个多重背包 每次去掉一个物品 询问钱数为w所能买到的最大值. 可以对于每次Q暴力dp 利用单调队列优化多重背包 这样复杂度是Qnm的. 发现过不了n==10的点 ...
- 题解——洛谷P4095 [HEOI2013]Eden 的新背包问题(背包)
思路很妙的背包 用了一些前缀和的思想 去掉了一个物品,我们可以从前i-1个和后i+1个推出答案 奇妙的思路 #include <cstdio> #include <algorithm ...
- LUOGU P4095 [HEOI2013]Eden 的新背包问题
题目描述 " 寄 没 有 地 址 的 信 ,这 样 的 情 绪 有 种 距 离 ,你 放 着 谁 的 歌 曲 ,是 怎 样 的 心 情 . 能 不 能 说 给 我 听 ." 失忆的 ...
- Luogu P4095 [HEOI2013]Eden 的新背包问题 思维/动规
当时一直在想前缀和...多亏张队提醒... 从1到n背次包,保存每一个状态下的价值,就是不要把第一维压掉:再从n到1背一次,同样记住每种状态: 然后询问时相当于是max(前缀+后缀),当然前缀后缀中间 ...
- Luogu P4095 [HEOI2013]Eden的新背包问题
题目 求出从前往后的背包\(f_{i,j}\)和从后往前的背包\(F_{i,j}\). 那么对于询问\((d,e)\),答案就是\(\max\limits_{i=0}^e f_{d-1,i}+F_{d ...
随机推荐
- 自动化测试框架PatatiumWebUi
PatatiumWebUi 官网:https://git.oschina.net/zhengshuheng/PatatiumWebUi 这是Java编写的框架,基于Selenium.TestNG等技术 ...
- discuz邮箱注册激活||腾讯企业邮箱免费注册及登录方法
如何申请免费的企业邮箱,如果拥有了网站,还能有一个免费的域名邮箱,是不是很拉风呢?对于还没有注册企业的用户来说,优先使用企业邮箱,是非常好的事呢. 腾讯邮箱现在开放免费的企业邮箱注册,效果要比个人邮箱 ...
- Spring MVC 注解开发详解
@Controller控制器定义 1.Controller是单利模式,被多个线程请求共享,因此设计成无序状态. 2.通过@controller标注即可将class定义为一个controller类.为使 ...
- Java(一)——认识Java语言
1.Java语言简介 Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言,具有卓越的通用性.高效性.平台移植性和安全性.Sun 公司对 Java 编程语言的解释是:Java 编程语言是个简单 ...
- myeclipse_JUnit导包问题
第一种方式: MyEclipse创建JUnit单元测试时,在需要测试的代码段前键入“@Test”时,按ctrl和1一般会自动提示JUnit需要导包,但有时会无法提示这个建议,如图所示.该经验教你如何解 ...
- 【旧文章搬运】ntfs中的文件名排序规则~
原文发表于百度空间,2011-04-05========================================================================== 在分析nt ...
- CS231n 2016 通关 第四章-NN 作业
cell 1 显示设置初始化 # A bit of setup import numpy as np import matplotlib.pyplot as plt from cs231n.class ...
- Linux启动eclipse报错找不到java环境解决方法
在Linux mint下,前几天还用得很好的的eclipse,今天开机不知为什么这样. Eclipse 3.6 在 linux mint 12 可以在终端顺利启动Eclipse,但是鼠标双击,或者用起 ...
- js中实现子页面向父页面中赋值
(方法一) 父页面: <input id="input1" type="text"/> <a href="javascript:wi ...
- C++ windows 多线程 互斥锁
#include <opencv2/core/version.hpp> #include <opencv2/calib3d/calib3d.hpp> #include < ...