【NOIP2011】观光公交
题解:贪心策略----使用一次加速器,只会对当前第i站车上的乘客以及已经到第i+1站的乘客做出贡献,每次贪心寻找到最优的站台加速即可。
#include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> #include<vector> #include<set> #include<cstring> #include<queue> #include<stack> #define MAXN 200010 #define LL long long int using namespace std; const int INF=1e9; const int EPS=1e-8; struct node{ int T; int A; int B; }a[MAXN]; int n,m,k; int ans; int d[MAXN];//从i到i+1的时间 int t[MAXN];//到达i的时刻 int f[MAXN];//最晚到达i的乘客的时刻 int g[MAXN];//在i车站加速最大影响到的车站 int sum[MAXN];//前i个车站下车的人数 int main() { freopen("1.in","r",stdin); // freopen("1.out","w",stdout); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n-1;i++) scanf("%d",&d[i]); for(int i=1;i<=m;i++) { scanf("%d%d%d",&a[i].T,&a[i].A,&a[i].B); f[a[i].A]=max(f[a[i].A],a[i].T);//求出最晚到的乘客时刻 sum[a[i].B]++; } for(int i=2;i<=n;i++) sum[i]+=sum[i-1];//前缀和求人数 t[1]=0; for(int i=2;i<=n;i++) t[i]=max(t[i-1],f[i-1])+d[i-1];//当前到达i的时刻 for(int i=1;i<=m;i++) ans+=t[a[i].B]-a[i].T;//旅游时间 while(k>0) { g[n]=n; g[n-1]=n; for(int i=n-2;i;i--) { if(t[i+1]<=f[i+1])//如果下一站的需要等待的乘客到达时间大于到达的时刻,那么在i+1车站之后站下车的乘客不会收到在i加速的影响 g[i]=i+1; else g[i]=g[i+1]; } int maxl=0,j; for(int i=1;i<=n;i++) if(sum[g[i]]-sum[i]>maxl&&d[i]>0)//找到影响最多人的车站,贪心策略 maxl=sum[g[i]]-sum[i],j=i; if(!maxl) break; ans-=maxl; d[j]--;//加速 k--;//少了一个 t[1]=0; for(int i=2;i<=n;i++) t[i]=max(t[i-1],f[i-1])+d[i-1];//再次贪心 } cout<<ans<<endl; return 0; }