贪心做法:
如果要贪心的话肯定是从影响人数最多的路径入手,在其中某个路径使用加速器的话一定对后面的路径都有影响吗?
我们可以分类讨论一下:
1.如果加速之后,下一个点还是需要等待,那么对以后将不会有影响。
2.如果加速之后不需要等待了,那么对以后的时间一直加到1或者最后一个点为止。
用数组sum[i]表示到i点的人数,g[i]表示i这个点所能影响到的最远点。
那么sum[i+g[i]]-sum[i]就为能影响到的人数。
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=30001;
int n,m,k;
int dis[maxn],last[maxn],g[maxn],enter[maxn];//sum,g,都说过了,enter表示公交车到i点的最短时间,last表示最后一人到i点的时间。dis表示两点间的距离。
int ans,sum[maxn],maxx=-1;
struct node
{
int time,start,end;
}a[maxn];//存边的信息。
inline void bus(int x)
{
while(x)
{
x--;
g[n]=g[n-1]=n;
int tar;
maxx=-1;
for(int i=n-2;i>=1;i--)
{
if(enter[i+1]<=last[i+1]) g[i]=i+1;
else g[i]=g[i+1];
}
for(int i=1;i<n;i++)
{
int tmp=sum[g[i]]-sum[i];
if(tmp>maxx&&dis[i]>0)
{
maxx=tmp;tar=i;
}
}
ans-=maxx;
dis[tar]--;
for(int i=2;i<=n;i++)
enter[i]=max(enter[i-1],last[i-1])+dis[i-1];
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<n;i++)
scanf("%d",&dis[i]);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].time,&a[i].start,&a[i].end);
for(int i=1;i<=m;i++)
{
last[a[i].start]=max(last[a[i].start],a[i].time);
sum[a[i].end]++;
}
enter[1]=last[1];
for(int i=1;i<=n;i++)
sum[i]+=sum[i-1];
for(int i=2;i<=n;i++)
enter[i]=max(enter[i-1],last[i-1])+dis[i-1];
for(int i=1;i<=m;i++)
ans+=enter[a[i].end]-a[i].time;
bus(k);
printf("%d\n",ans);
return 0;
}