【问题描述】
小Y最近开发出了批量制造大威力轰山炮的方法。才过去不到几个月,小Y就制造出了M门款式不同的轰山炮。第i门轰山炮发射一次,能使一座当前高度不高于Ai的山的高度降低Di(当然山的高度不能轰到0以下)。应政府要求,小Y要用他开发的轰山炮轰平开发
区的几座山。由于开发区急需土地资源,政府要求小Y轰平尽量多的山(轰平:使山的高度降低至0)。但是小Y制造的弹药有限,导致他最多只能发射K次。小Y想知道,他最多能轰平几座山?轰平这些山后,弹药最多还够他发射几次?
【问题分析】
贪心
如果一个炮相比于另一个炮(意大利),打的没它高,削减高度没它多,那你还用它干毛?对不对。这样的话时间代价O(NM),但是我常数写的大,O(10^7)过了一半的点。MD。
优化
预处理出所有山都需要几炮干掉 虽然确定是一个个连续的区间,但是山太高了 存不下啊 而且还存在特殊数据 比如说某一个炮d>h的时候,当山高h+1时,并且下一个炮d>h+1时,就不好处理。。。
所以 咋整? 考试的时候真的没有想出来。
观察 D<=500 ???
所以说为了避免上述情况 可以将每一个炮的[h-d,h]处理出来就可以了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
#define ll long long
const int N=250001;
const int M=501;
map<ll,ll> f;
struct gg {ll h;int d;}pao[M],use[M];
int n,m,cnt; ll hill[N]; ll k,ans;
ll readin()
{
ll x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
}
bool cmp(gg a,gg b)
{
if (a.h==b.h)
return a.d<b.d;
return a.h<b.h;
}
void read()
{
int i;
n=readin(); m=readin(); k=readin();
for (i=n;i>=1;i--)
hill[i]=readin();
for (i=1;i<=m;i++)
pao[i].h=readin(),pao[i].d=readin();
sort(pao+1,pao+1+m,cmp);
pao[0]=(gg){0,0};
for (i=1;i<=m;i++)
{
while(cnt&&use[cnt].d<=pao[i].d) cnt--;
use[++cnt]=pao[i];
}
use[0]=(gg){0,0};
return;
}
long long mymax(long long a,long long b){return a>b?a:b;}
void solve()
{
ll now=0,l,j,tmp; int i;
f[0]=0;
for (i=1;i<=cnt;i++)
{
now=use[i-1].h;
l=mymax(now,use[i].h-use[i].d);
for (j=l+1;j<=use[i].h;j++)
{
tmp=(j-now-1)/use[i].d+1;
f[j]=f[mymax(0,j-(use[i].d*tmp))]+tmp;
}
}
return;
}
void work()
{
int i,j=1; ll now,tmp,need;
for (i=1;i<=n;i++)
{
while(j<=cnt&&use[j].h<hill[i]) j++;
if (j>cnt)
{
printf("%d %lld\n",i-1,k-ans);
return;
}
now=use[j-1].h;
tmp=(hill[i]-now-1)/use[j].d+1;
need=f[mymax(0,hill[i]-(use[j].d*tmp))]+tmp;
if (ans+need>k)
{
printf("%d %lld\n",i-1,k-ans);
return;
}
ans+=need;
}
printf("%d %lld\n",n,k-ans);
return;
}
int main()
{
freopen("canon.in","r",stdin);
freopen("cannon.out","w",stdout);
read();
solve();
work();
return 0;
}