【JZOJ4863】Market

Description

现在有一些物品,第 i 个物品的花费,价值,出现的时间分别为ci vi ti ,每个物品只能获得一次,现在对于每个询问 Ti Mi ,表示在 Ti 时刻购买,预算为M_i,求获得的最大价值。

Data Constraint

n300,m105
ci,Mi109,vi300
ti,Ti300

Solution

对询问和物品按照时间排序,按照询问依次加入物品。

Fi 表示花费 i 获得的最大价值,但我们发现这样时间空间都超出范围。

我们发现价值很小,于是我们可以设Fi表示获得价值 i <script type="math/tex" id="MathJax-Element-871">i</script>所用的最小花费,转移与上面的方法类似。

找答案时就取个后缀最小值,二分答案即可。

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]);
}
posted @ 2016-11-05 16:22  sadstone  阅读(51)  评论(0编辑  收藏  举报