观光公交——堆优化

来源:互联网 发布:高成本网络大电影 编辑:程序博客网 时间:2024/04/29 09:41

题意:2011noip原题,不再赘述。

之前贪心的做法固然是正确的。但一个一个加速器用显得太慢了,能不能一次性使用多个加速器呢?
答案完全是可以的,同之前贪心策略类似的,关注每站的T_up_max和T_down_max,以及每站的下车人数,并将其前缀和维护。 那么就找max(T_down_max-T_up_max),即使用加速器的个数。

#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--) #define LL long long #define INF 0x3f3f3f3f#define N 1005#define M 10005#define S 100005using namespace std;int n,m,k;int ans;int dis[N];int down[M],up[M];int sum[N],g[N];struct node{    int t,s,e;}A[M];struct Node{    int L,R;    bool operator<(const Node &a)const{        return sum[R]-sum[L]<sum[a.R]-sum[a.L];     }};priority_queue<Node>Q;void Init(){    REP(i,1,m)sum[A[i].e]++,up[A[i].s]=max(up[A[i].s],A[i].t);    REP(i,1,n)down[i]=max(down[i-1],up[i-1])+dis[i-1];    REP(i,1,n)sum[i]+=sum[i-1];    REP(i,1,m)ans+=down[A[i].e]-A[i].t;}   void solve(){    Q.push((Node){1,n});    while(!Q.empty()&&k){        int l=Q.top().L,r=Q.top().R;        Q.pop();        int Mx=min(k,dis[l]),pos=-1;        REP(i,l+1,r-1)if(down[i]-up[i]<Mx)Mx=down[i]-up[i],pos=i;        if(Mx>0){            k-=Mx;            ans-=(sum[r]-sum[l])*Mx;            dis[l]-=Mx;            REP(i,1,n)down[i]=max(down[i-1],up[i-1])+dis[i-1];        }        if(pos!=-1){            if(l<pos)Q.push((Node){l,pos});            if(pos<r)Q.push((Node){pos,r});        }        else if(l+1<r)Q.push((Node){l+1,r});    }}int main(){    scanf("%d%d%d",&n,&m,&k);    REP(i,1,n-1)scanf("%d",&dis[i]);    REP(i,1,m)scanf("%d%d%d",&A[i].t,&A[i].s,&A[i].e);    Init();    solve();    printf("%d\n",ans);    return 0;}
原创粉丝点击