• [NOIP2011]观光公交 题解


    题目大意:

      就省了吧

    思路:

      应该算是贪心。

      不难发现,加速只对所有在使用加速器之后连续的一段下车时不用等人的站点下车的人有用。这非常重要。

      先算出不加速时的和,并预处理出每个站点最迟到的人的时间、每个站下车的人数。然后一个一个放加速器,加速器放在惠及最多的人的一段,同时维护到每个站点的时间(判断用不用等人)。

      于是就有了一种比较暴力的算法:每次n2暴力求解每次加速后停下来的站点,再修改答案、维护数组。

      但是这似乎会TLE(虽然官方数据貌似AC了),于是就有了优化。你可以逆推求解停下来的站点,再用前缀和O(n)求解人数。

    代码:

      暴力:

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 const int M=100005,N=1005;
     5 int n,m,k,i,j,mx,ans,t[M],off[M],last[M],come[M],down[M],dist[N];
     6 
     7 int read()
     8 {
     9     int x=0;
    10     char ch=getchar();
    11     while (ch<'0' || ch>'9') ch=getchar();
    12     while (ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    13     return x;
    14 }
    15 
    16 int main()
    17 {
    18     n=read(),m=read(),k=read();
    19     for (i=1;i<n;i++) dist[i]=read();
    20     for (i=1;i<=m;i++) t[i]=read(),last[j=read()]=max(last[j],t[i]),off[down[i]=read()]++;
    21     for (i=1;i<n;i++) come[i+1]=max(come[i],last[i])+dist[i];
    22     for (i=1;i<=m;i++) ans+=come[down[i]]-t[i];
    23     while (k--)
    24     {
    25         for (i=1;i<=n;i++) t[i]=0;
    26         for (i=1;i<n;i++)
    27             if (dist[i])
    28                 for (j=i+1;j<=n;j++)
    29                 {
    30                     t[i]+=off[j];
    31                     if (come[j]<=last[j]) break;
    32                 }
    33         mx=0;
    34         for (i=1;i<n;i++)
    35             if (t[i]>mx) mx=t[i],j=i;
    36         dist[j]--,ans-=t[j],come[++j]--;
    37         for (;j<n;j++) come[j+1]=max(come[j],last[j])+dist[j];
    38     }
    39     printf("%d
    ",ans);
    40     return 0;
    41 }

       优化:

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 const int M=100005,N=1005;
     5 int n,m,i,j,k,mx,ans,t[M],far[N],sum[N],off[M],last[M],come[M],dist[N];
     6 
     7 int read()
     8 {
     9     int x=0; char ch=getchar();
    10     while (ch<'0' || ch>'9') ch=getchar();
    11     while (ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    12     return x;
    13 }
    14 
    15 int main()
    16 {
    17     n=read(),m=read(),k=read();
    18     for (i=1;i<n;i++) dist[i]=read();
    19     for (i=1;i<=m;i++) t[i]=read(),last[j=read()]=max(last[j],t[i]),sum[off[i]=read()]++;
    20     for (i=1;i<n;i++) come[i+1]=max(come[i],last[i])+dist[i];
    21     for (i=1;i<=m;i++) ans=ans+come[off[i]]-t[i];
    22     for (i=1;i<=n;i++) sum[i]=sum[i]+sum[i-1];
    23     while (k--)
    24     {
    25         far[n-1]=n,mx=0;
    26         for (i=n-2;i;i--)
    27             if (come[i+1]>last[i+1]) far[i]=far[i+1]; else far[i]=i+1;
    28         for (i=1;i<n;i++)
    29             if (sum[far[i]]-sum[i]>mx && dist[i]) mx=sum[far[i]]-sum[i],j=i;
    30         if (!mx) break; --dist[j],ans=ans-mx;
    31         for (come[1]=0,i=1;i<n;i++) come[i+1]=max(come[i],last[i])+dist[i];
    32     }
    33     printf("%d
    ",ans);
    34     return 0;
    35 }
  • 相关阅读:
    3月16日
    11月8日
    Code4 APP
    为什么alertView弹出后button会消失的问题
    设置某个类使用或者禁用ARC
    Bundle使用&NSBundle
    respondsToSelector
    NSDate获取当前时区的时间
    iOS enum 定义与使用
    IOS开发之纯代码界面--基本控件使用篇 ┊
  • 原文地址:https://www.cnblogs.com/HHshy/p/6011171.html
Copyright © 2020-2023  润新知