SOL
挺不错的一道贪心题,小学奥数的较多
最开始分析样例,很多人可能会考虑直接让所有氮气加速器用在下车人数最多的那个车站的前面那条路上,不过发现有车等人、人等车的问题之后,你可能就会觉得这道题不是一个贪心题了
事实上,这还是一道贪心题,只不过次氮气加速要一次一次的使用,这个思路应该能够在尝试推导的做法之后想到,用一次氮气加速时,我们考虑人等车的区间贡献最大的一段,并且保证用了之后不会变成车等人,也就是目前车到达站点的时间大于最晚到此站的人的时间,求出这么一段区间,然后对最前面那一段使用一次氮气加速,那么整个区间的时间都会减少,求出下车人数最多的一段即可
用了一次之后,可能会出现有些地方从人等车变成车等人,因此要从头考虑,做完次统计答案即可
复杂度
代码:
#include<bits/stdc++.h>
#define re register
using namespace std;
inline int rd(){
int data=0;static char ch=0;ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))data=(data<<1)+(data<<3)+(ch^48),ch=getchar();
return data;
}
const int M=1e4+5,N=1005;
int n,m,k,st[M],ed[M],ans,dis[N],off[N],last[N],beg[N],tim,mx,now,pos;
signed main(){
n=rd(),m=rd(),k=rd();
for(int re i=1;i^n;++i)dis[i]=rd();
for(int re v,i=1;i<=m;++i)st[i]=rd(),v=rd(),ed[i]=rd(),last[v]=max(last[v],st[i]),++off[ed[i]];
for(int re i=1;i<=n;++i)beg[i]=tim,tim=max(tim,last[i]),tim+=dis[i];
while(k--){
mx=0;
for(int re i=2;i<=n;++i){
if(!dis[i-1])continue;
now=0;
for(int re j=i;j<=n;++j){
now+=off[j];
if(beg[j]<=last[j])break;
}if(now>mx)mx=now,pos=i;
}--dis[pos-1];
for(int re i=pos;i<=n;++i){
--beg[i];
if(beg[i]<last[i])break;
}
}
for(int re i=1;i<=m;++i)ans+=beg[ed[i]]-st[i];
printf("%d",ans),exit(0);
}