zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    【design pattern】代理模式
    Java IO(十七)FIleReader 和 FileWriter
    Java IO(十六)InputStreamReader 和 InputStreamWriter
    Java IO(十五)FilterReader 和 FilterWriter、FilterReader 子类 PushBackReader
    Java IO(十四) CharArrayReader 和 CharArrayWriter
    Java IO(十三)PipedReader 和 PipedWriter
    Java IO(十二) 字符流 Writer 和 Reader
    Java IO(十一) DataInputStream 和 DataOutputStream
    Java IO(十) BufferedInputStream 和 BufferedOutputStream
    Java IO(九)FilterInputStream 和 FilterOutputStream
  • 原文地址:https://www.cnblogs.com/HHshy/p/6011171.html
Copyright © 2011-2022 走看看