1. 程式人生 > >【NOIP2017提高A組衝刺11.8】購物

【NOIP2017提高A組衝刺11.8】購物

Description

X 城的商場中,有著琳琅滿目的各種商品。一日,小X 帶著小Y 前來購物,小Y 一共看中了n件商品,每一件商品價格為Pi。小X 現在手中共有m個單位的現金,以及k 張優惠券。小X 可以在購買某件商品時,使用至多一張優惠券,若如此做,該商品的價格會下降至Qi。
小X 希望儘可能多地滿足小Y 的願望,所以小X 想要知道他至多能購買多少件商品。

Input

第一行包含三個整數n,k,m,表示商品總數,小X 擁有的優惠券與現金總數。
接下來n行每行包含兩個整數Pi,Qi。

Output

共一行包含一個整數,表示小X 至多能購買的物品數。

Sample Input

4 1 7
3 2
2 2
8 1
4 3

Sample Output

3
樣例解釋:一種最優的購買方式是購買1,2,3號物品,並用優惠券購買物品3,總共花費為3+2+1=6。

Data Constraint

這裡寫圖片描述

題解

這題第一眼看是DP,可再看一眼卻是一道大水題——可撤銷貪心。
很明顯,這題需要兩個堆,一個存p,另一個存q,可是問題來了,優惠券最多隻有k張,怎麼辦?
這時加上第三個堆,表示撤銷操作,存p-q。
每次操作時,看一看p堆的堆頂和q堆堆頂+撤銷堆堆頂哪個小,就取哪個操作,但取q堆堆頂+撤銷堆堆頂時要在撤銷堆里加上一個p-q。
詳見程式碼(不要*標):

var
        n,k,i,s1,s2,ans,s3:longint;
        m:int64;
        d:array[0..100000,1..3,1..2]of longint;//1:p;2:q;3:cancel
        q,p,bz:array[0..100000]of longint;
        tot,j:array[1..3]of longint;
procedure up(x,u:longint);
var
        y:Longint;
        t:array[1..2]of longint;
begin
        while x>1
do begin y:=x div 2; if d[y,u,1]<=d[x,u,1] then break; t:=d[x,u]; d[x,u]:=d[y,u]; d[y,u]:=t; x:=y; end; end; procedure down(x,u:longint); var y:longint; t:array[1..2]of longint; begin while x*2<=tot[u] do begin y:=x*2; if (y+1<=tot[u])and(d[y,u,1]>d[y+1,u,1]) then inc(y); if d[y,u,1]>=d[x,u,1] then break; t:=d[x,u]; d[x,u]:=d[y,u]; d[y,u]:=t; x:=y; end; end; procedure inp(x,cc,y:longint); begin inc(tot[y]); d[tot[y],y,1]:=x; d[tot[y],y,2]:=cc; up(tot[y],y); end; function outp(y:longint):longint; var jl:longint; begin jl:=d[1,y,1]; j[y]:=d[1,y,2]; d[1,y]:=d[tot[y],y]; dec(tot[y]); down(1,y); while (bz[j[y]]=1)and(tot[y]>0)and(y<>3) do begin jl:=d[1,y,1]; j[y]:=d[1,y,2]; d[1,y]:=d[tot[y],y]; dec(tot[y]); down(1,y); end; exit(jl); end; begin readln(n,k,m); for i:=1 to n do begin readln(p[i],q[i]); inp(p[i],i,1); inp(q[i],i,2); end; for i:=1 to k do inp(0,i,3); while (m>0)and(ans<n) do begin s1:=outp(1); s2:=outp(2); s3:=outp(3); if s2+s3<s1 then begin inp(s1,j[1],1); dec(m,s2+s3); if m<0 then break; inc(ans); inp(p[j[2]]-q[j[2]],5,3); bz[j[2]]:=1; end else begin inp(s2,j[2],2); inp(s3,j[3],3); dec(m,s1); if m<0 then break; inc(ans); bz[j[1]]:=1; end; end; writeln(ans); end.