【贪心】NOIP2011观光巴士

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/82584725

分析:

其实是非常简单的贪心水题。。。

这题每个人有个上车时间,这会限制公交车从每个站点的出发时间。(注意,这里要把“到达时间”和“出发时间”区分开,不一定到达了就瞬间出发)。

首先,可以先算出到达每个站点的时间,这可以O(n)一遍算出来。(把到达时间,和从这里出发的最晚的一个人的时间取max,作为出发时间,然后再加上到达下一个点的路程,作为下一个点的到达时间,以此类推)

观察我们求值的方式,不难发现:如果某个点的到达时间,已经早于出发时间了,说明巴士是一定等了乘客的。这时候,无论在前面任何一个点加速,都无法影响到这个点后面的站点的到达时间。因为无论加多少,都会在这个站点停下来,等乘客。

所以在某个点加速,会影响到达时间的站点,就是从这里以后,到达的最近的一个:到达时间不超过出发时间的站点。

然后存下每个点加速1单位的贡献,用个优先队列就行了。更新靠线段树就可以了。(话说区间更改我居然没用懒标记。。。真的是昏了头了)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 1010
#define MAXM 10010
#define INF 0x3FFFFFFF
using namespace std;
typedef long long ll;
int n,m,k;
int d[MAXN],maxt[MAXN],las[MAXN],tx[MAXN];
int lp[MAXM],rp[MAXM],t[MAXM];
priority_queue<pair<int,int> > q;
int siz[MAXN];
int tree[MAXN*4],add[MAXN],tag[MAXN*4];
void build(int l,int r,int id){
    if(l==r){
        tree[id]=add[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,id*2);
    build(mid+1,r,id*2+1);
    tree[id]=min(tree[id*2],tree[id*2+1]);
}
void pushdown(int x){
    tree[x*2]-=tag[x];
    tree[x*2+1]-=tag[x];
    tag[x*2]+=tag[x];
    tag[x*2+1]+=tag[x];
    tag[x]=0;
}
void change(int l,int r,int id,int pl,int pr){
    if(l!=r)
        pushdown(id);
    if(l>=pl&&r<=pr){
        tree[id]--;
        tag[id]++;
        return ;
    }
    int mid=(l+r)>>1;
    if(pl<=mid)
        change(l,mid,id*2,pl,pr);
    if(pr>mid)
        change(mid+1,r,id*2+1,pl,pr);
    tree[id]=min(tree[id*2],tree[id*2+1]);
}
int que(int l,int r,int id,int pl,int pr){
    if(l!=r)
        pushdown(id);
    if(l>=pl&&r<=pr){
        return tree[id];
    }
    int res=INF;
    int mid=(l+r)>>1;
    if(pl<=mid)
        res=min(res,que(l,mid,id*2,pl,pr));
    if(pr>mid)
        res=min(res,que(mid+1,r,id*2+1,pl,pr));
    return res;
}
int update(int x){
    int res=0;
    while(las[x]!=x&&que(1,n,1,x,las[x]-1)==0){
        res+=siz[las[x]+1];
        las[x]--;
    }
    return res;
}
int main(){
    SF("%d%d%d",&n,&m,&k);
    for(int i=1;i<n;i++)
        SF("%d",&d[i]);
    for(int i=1;i<=m;i++){
        SF("%d%d%d",&t[i],&lp[i],&rp[i]);
        siz[rp[i]]++;
        maxt[lp[i]]=max(maxt[lp[i]],t[i]);
    }
    int tims=0;
    for(int i=1;i<=n;i++){
        tx[i]=tims;
        tims=max(tims,maxt[i]);
        tims+=d[i];
        add[i]=max(0,tims-maxt[i+1]);
    }
    ll ans=0;
    for(int i=1;i<=m;i++)
        ans+=tx[rp[i]]-t[i];
    for(int i=1;i<=n;i++){
        int res=0;
        for(int j=i;j<=n;j++){
            las[i]=j;
            res+=siz[j+1];
            if(add[j]==0)
                break;
        }
        q.push(make_pair(res,i));
    }
    build(1,n,1);
    while(k--&&!q.empty()){
        pair<int,int> now=q.top();
        q.pop();
        int x=now.second;
        int cnt=0;
        for(int i=x;;i++){
            cnt+=siz[i+1];
            if(que(1,n,1,i,i)==0)
                break;
        }
        if(d[x]==0){
            k++;
            continue;
        }
        if(now.first==0)
            break;
        if(las[x]!=x&&que(1,n,1,x,las[x]-1)==0){
            now.first-=update(x);
            q.push(now);
            k++;
            continue;
        }
        d[x]--;
        ans-=now.first;
        if(las[x]>x)
            change(1,n,1,x,las[x]-1);
        q.push(now);
    }
    PF("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/82584725
今日推荐