【GDOI2017】Market

8 篇文章 0 订阅
5 篇文章 0 订阅

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

可以发现,对于某个询问,开张时间超过计划的是没有贡献的,显然就可以通过以时间为第一关键字排序,用个指针添加有贡献的商店。分析数据后发现,总价值最大不超过9000。设 fi 为当答案为i时,需要花费 fi 的价值,设 gi min(gi,gi+1,gi+2,) ,得到了这样的一个g数组后,我们就可以二分了:对于每一次二分出的mid,判断一下 gmid 是否小于等于计划的预算,如果是则符合要求。

Code

var
    f,g:array[0..100000] of longint;
    a:array[0..305,1..3] of longint;
    q:array[0..100000,1..3] of longint;
    ans:array[0..100000] of longint;
    n,m,i,j,mx,maxn,l,r,mid:longint;
function min(x,y:longint):longint;
begin
    if x<y then exit(x) else exit(y);
end;
procedure qsort1(l,r:longint);
var i,j,mid:longint;
begin
    i:=l;j:=r;
    mid:=a[(i+j)div 2,3];
    repeat
        while a[i,3]<mid do inc(i);
        while mid<a[j,3] do dec(j);
        if i<=j then
        begin
            a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
            inc(i); dec(j);
        end;
    until i>j;
    if i<r then qsort1(i,r);
    if l<j then qsort1(l,j);
end;
procedure qsort2(l,r:longint);
var i,j,mid:longint;
begin
    i:=l;j:=r;
    mid:=q[(i+j)div 2,1];
    repeat
        while q[i,1]<mid do inc(i);
        while mid<q[j,1] do dec(j);
        if i<=j then
        begin
            q[0]:=q[i];q[i]:=q[j];q[j]:=q[0];
            inc(i); dec(j);
        end;
    until i>j;
    if i<r then qsort2(i,r);
    if l<j then qsort2(l,j);
end;
begin
    readln(n,m);
    for i:=1 to n do
    begin
        readln(a[i,1],a[i,2],a[i,3]);
        maxn:=maxn+a[i,2];
    end;
    for i:=1 to m do
    begin
        readln(q[i,1],q[i,2]);
        q[i,3]:=i;
    end;
    qsort1(1,n); qsort2(1,m);
    mx:=0;
    fillchar(f,sizeof(f),$7f);
    fillchar(g,sizeof(g),$7f);
    f[0]:=0;
    for i:=1 to m do
    begin
        while (mx<n)and(a[mx+1,3]<=q[i,1]) do
        begin
            inc(mx);
            for j:=maxn-a[mx,2] downto 0 do
                if f[j]<=1000000000 then f[j+a[mx,2]]:=min(f[j+a[mx,2]],f[j]+a[mx,1]);
            for j:=maxn downto 0 do
                if f[j]<=1000000000 then g[j]:=min(g[j+1],f[j]) else g[j]:=g[j+1];
        end;
        l:=0;r:=maxn;
        while l<r do
        begin
            mid:=(l+r) div 2;
            if g[mid]<=q[i,2] then
            begin
                ans[q[i,3]]:=mid;l:=mid+1;
            end else r:=mid-1;
        end;
        if g[l]<=q[i,2] then ans[q[i,3]]:=l;
    end;
    for i:=1 to m do writeln(ans[i]);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值