Luogu P1315 观光公交

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P1315 观光公交相关的知识,希望对你有一定的参考价值。

题目
每次把加速器用在可以是答案减少最多的地方就即可。(这不是废话吗?)
具体而言,我们处理出:
(sum_i)(i)为止下车人数之和。
(t_i)(i)最晚的上车的人的上车时间。
(a_i)表示到达(i)的时间。
那么我们做(k)次,每次先处理出:
(l_i)表示在(i)使用加速器,能够使得出发时间减一的最后位置。
然后找贡献最大的,更新(t,a,l)即可。

#include<bits/stdc++.h>
using namespace std;
int read(){int x=0;char c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
int max(int a,int b){return a>b? a:b;}
const int N=1001,M=10001;
int d[N],T[M],A[M],B[M],t[N],s[N],a[N],l[N];
int main()
{
    int n=read(),m=read(),k=read(),ans=0,mx,p,i;
    for(i=1;i<n;++i) d[i]=read();
    for(i=1;i<=m;++i) T[i]=read(),A[i]=read(),B[i]=read(),t[A[i]]=max(t[A[i]],T[i]),++s[B[i]];
    for(i=2;i<=n;++i) s[i]=s[i]+s[i-1];
    for(a[1]=0,i=2;i<=n;++i) a[i]=max(a[i-1],t[i-1])+d[i-1];
    for(i=1;i<=m;++i) ans+=a[B[i]]-T[i];
    while(k--)
    {
        l[n-1]=n,mx=0;
    for(i=n-2;i;--i) l[i]=a[i+1]<=t[i+1]? i+1:l[i+1];
    for(i=1;i<n;++i) if(s[l[i]]-s[i]>mx&&d[i]) mx=s[l[i]]-s[i],p=i;
        ans-=mx,--d[p];
        for(i=p+1;i<=n;++i) a[i]=max(a[i-1],t[i-1])+d[i-1];
    }
    return !printf("%d",ans);
}

(O(n^2))
考虑性质,原图由于必须要等乘客的缘故,肯定被分成若干段。
每段选最靠左的端点必定最优,我们找出最优的段,一直加满,直到新增了一段。
这样每次操作必定增加一段,只会进行(O(n))次。
(O(nlog n))
由于段之间是没有影响的,所以可以用优先队列来维护不同的段的最大值,再用数据结构维护每段还需要加多少才会满。

以上是关于Luogu P1315 观光公交的主要内容,如果未能解决你的问题,请参考以下文章

LUOGU P1315 观光公交(贪心)

P1315 观光公交 贪心

洛谷P1315 观光公交

P1315 观光公交

[NOIP2011] 提高组 洛谷P1315 观光公交

P1315 观光公交 - 贪心