码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P1315 观光公交

时间:2019-09-27 15:23:05      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:max   需要   git   clu   code   print   tps   答案   const   

题目
每次把加速器用在可以是答案减少最多的地方就即可。(这不是废话吗?)
具体而言,我们处理出:
\(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 观光公交

标签:max   需要   git   clu   code   print   tps   答案   const   

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11597791.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!