观光公交noip<贪心>
题目链接:https://www.oj.swust.edu.cn/problem/show/1190
思路:
每在一段路上使用一次加速器,就会对某些人或者说某些路段上的人产生影响,目的是使产生的影响最大。
假设在路段x(x路段链接的是x--x+1两个景点)上使用了一次加速器,并且,到达x+1点后,需要等待,那么这次加速只会影响x+1点下车的人。
对以后的点没有影响。因为加速的那段时间被等待了。什么情况下才要等待呢?在不加速的情况下等待或者时间刚好的时候。如果不等待,那么这次在x路
段的加速相当于也在x+1路段上加速了。那么这个影响可以用递推的方式一次性全部求出来。设g[x]表示在x路段上加速会影响的景点。
g[n-1]=n;
for(int i=n-2;i>0;i--)
{ if(ti[i+1]>t[i+1])//表示车到达i+1点的时间要大于人到齐的时间 g[i]=g[i+1]; else g[i]=i+1; }
求得了可以影响的最远的点,那么就可以影响的总时间就等于在每个被影响的点下车的人数相加,维护前缀和就行,最后要去每次加速影响的最大值就行。
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1050; struct node { int arr,st,ed;//到达车站的时间,起点,终点。 }id[maxn*10]; int t[maxn];//最晚时间 int ti[maxn];//到达时间 int sum[maxn];//effect int dis[maxn];// int g[maxn]; int n,m,k; void init () { memset(t,0,sizeof(t)); memset(sum,0,sizeof(sum)); } int main() { while(~scanf("%d%d%d",&n,&m,&k)) { init(); for(int i=1;i<n;i++) scanf("%d",&dis[i]); for(int i=1;i<=m;i++) { scanf("%d%d%d",&id[i].arr,&id[i].st,&id[i].ed); t[id[i].st]=max(t[id[i].st],id[i].arr);//到大某点的最晚时间 sum[id[i].ed]++;//到达某点的人数 } for(int i=2;i<=n;i++) sum[i]+=sum[i-1]; for(int i=1;i<=n;i++) ti[i]=max(ti[i-1],t[i-1])+dis[i-1]; int ans=0; for(int i=1;i<=m;i++) ans+=ti[id[i].ed]-id[i].arr; while(k)// { g[n-1]=n; for(int i=n-2;i>0;i--) { if(ti[i+1]>t[i+1]) g[i]=g[i+1]; else g[i]=i+1; } int pos=0,ma=0; for(int i=1;i<n;i++) { if(dis[i]&&(sum[g[i]]-sum[i])>ma) { ma=sum[g[i]]-sum[i]; pos=i; } } if(!ma) break; k--; dis[pos]--; ans-=ma; for(int i=1;i<=n;i++) ti[i]=max(ti[i-1],t[i-1])+dis[i-1]; } printf("%d\n",ans); } return 0; }
想的太多,做的太少。