您的位置:首页 > 其它

【GDOI2017模拟11.5】Market

2016-11-05 15:38 387 查看

Description



Input



Output

m行,每行一个整数,表示答案

Sample Input

5 2

5 5 4

1 3 1

3 4 3

6 2 2

4 3 2

3 8

5 9

Sample Output

10

12

Data Constraint



Solution

一眼可以看出,这是一个01背包问题

但是有了商店开门时间这个限制,还有它的钱数(代价)特别大。

但是总价值特别小,仅仅为300∗300=90000。

那么离线做。

将商店和方案都按照时间顺序排序,对于每一个方案,所有时间比它小或等于的商店都必须先做过

正常的背包是f[i]表示花了i元钱,最大的价值

现在用f[i]表示价值为i,最小的钱

转移显然

求答案时二分一下,二分钱要求一个后缀最小值

Code

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define ll long long
#define fo(i,a,b) for(ll i=a;i<=b;i++)
#define fd(i,a,b) for(ll i=a;i>=b;i--)
#define N 901000
using namespace std;
ll f
,g
,ans
,n,m;
struct node{
ll t,v,w;
};
node q
,a
;
bool cnt(node x,node y) {return x.t<y.t;}
ll find(ll k)
{
int l=0,r=100000;
while(l+1<r)
{
int mid=(l+r)/2;
if(g[mid]<=k) l=mid;else r=mid;
}
return l;
}
int main()
{
freopen("market.in","r",stdin);freopen("market.out","w",stdout);
scanf("%lld%lld",&n,&m);
fo(i,1,n) scanf("%lld%lld%lld",&a[i].v,&a[i].w,&a[i].t);
fo(i,1,m) scanf("%lld%lld",&q[i].t,&q[i].w),q[i].v=i;
sort(q+1,q+m+1,cnt);sort(a+1,a+n+1,cnt);
a[n+1].t=1000;
ll k=1;
memset(f,127,sizeof(f));memset(g,127,sizeof(g));f[0]=0;
while(q[k].t<a[1].t&&k<=m) ans[q[k].v]=0,k++;
fo(i,1,n)
{
fd(j,100000,0)
{
if(j>=a[i].w) f[j]=min(f[j],f[j-a[i].w]+a[i].v);
g[j]=min(g[j],min(f[j],g[j+1]));
}
while(a[i+1].t>q[k].t&&k<=m) ans[q[k].v]=find(q[k].w),k++;
}
while(k<=m) ans[q[k].v]=find(q[k].w),k++;
fo(i,1,m) printf("%lld\n",ans[i]);
fclose(stdin);fclose(stdout);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: