Description
现在有一些物品,第
i
个物品的花费,价值,出现的时间分别为
Data Constraint
n≤300,m≤105
ci,Mi≤109,vi≤300
ti,Ti≤300
Solution
对询问和物品按照时间排序,按照询问依次加入物品。
设 Fi 表示花费 i 获得的最大价值,但我们发现这样时间空间都超出范围。
我们发现价值很小,于是我们可以设
找答案时就取个后缀最小值,二分答案即可。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 310
#define M 100010
#define ll long long
using namespace std;
struct node{
int c,v,t;
}b[N];
struct node1{
int m,t,c;
}c[M];
int f[M],g[M+1];
int z[M];
bool cmp(node x,node y)
{
return x.t<y.t;
}
bool cmp1(node1 x,node1 y)
{
return x.t<y.t;
}
int main()
{
freopen("market.in","r",stdin);
freopen("market.out","w",stdout);
int n,m;
cin>>n>>m;
fo(i,1,n) scanf("%d %d %d",&b[i].c,&b[i].v,&b[i].t);
fo(i,1,m) scanf("%d %d",&c[i].t,&c[i].m),c[i].c=i;
sort(b+1,b+n+1,cmp);
sort(c+1,c+m+1,cmp1);
int q=0;
memset(f,60,sizeof(f));
f[0]=0;
memset(g,60,sizeof(g));
fo(i,1,m)
{
while(b[q+1].t<=c[i].t && q<n)
{
q++;
g[M]=2147483647;
fd(j,M-1,0)
{
if(j>=b[q].v)
{
if(f[j]>f[j-b[q].v]+b[q].c)
{
f[j]=f[j-b[q].v]+b[q].c;
}
}
g[j]=min(f[j],g[j+1]);
}
g[0]=0;
}
int ans=0;
int l=0,r=M-1;
while(l+1<r)
{
int mid=(l+r)/2;
if(g[mid]<=c[i].m) l=mid;
else r=mid;
}
ans=l;
if(g[r]<=c[i].m) ans=r;
z[c[i].c]=ans;
}
fo(i,1,m) printf("%d\n",z[i]);
}