zoukankan      html  css  js  c++  java
  • [NOIP2012]借教室 题解

    题目大意:

      有一个n个数的数列,m个操作,第i个操作使[li,ri]区间建di,问第几个操作使数列中出现负数。

    思路:

      暴力显然过不了,那么就可以优化了,不难想到线段树,显然需要良好的姿势,那么就差分。

      a[i]表示第i天比第i-1天多了多少房间,于是a的前缀和即为该天的房间数量。而a的维护显然为a[li]+=di,a[ri+1]-=di。

      因为求最前的操作,于是我们可以二分答案。但如此常数比较大,又有冗余,可以来个栈一样的东西节省时间。

      但是有大神想到了O(n+m)的算法。假设m个指令都可满足,天数从前往后判断,再从后往前一个一个删除指令,直到无负数为止。

    代码:

      二分:

     1 #include<cstdio>
     2 const int M=1000009;
     3 int n,m,i,k,h,t,sum,last,a[M],l[M],r[M],d[M],b[M];
     4 bool can;
     5 
     6 int read()
     7 {
     8     int x=0;
     9     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();
    18     for (i=1;i<=n;++i) b[i]=read();
    19     for (i=1;i<=m;++i) d[i]=read(),l[i]=read(),r[i]=read();
    20     for (h=1,t=m;h<t;)
    21     {
    22         m=h+t>>1;
    23         if (m>last) for (i=last+1;i<=m;++i) a[l[i]]=a[l[i]]+d[i],a[r[i]+1]=a[r[i]+1]-d[i];
    24         else if (m<last) for (i=m+1;i<=last;++i) a[l[i]]=a[l[i]]-d[i],a[r[i]+1]=a[r[i]+1]+d[i];
    25         for (last=m,sum=0,i=can=1;i<=n;++i)
    26         {
    27             sum=sum+a[i];
    28             if (sum>b[i]) { can=0; break; }
    29         }
    30         if (can) h=m+1; else t=k=m;
    31     }
    32     if (k) printf("-1
    %d
    ",k);
    33     else printf("0
    ");
    34     return 0;
    35 }

      O(n+m):

     1 #include<cstdio>
     2 const int M=1000005;
     3 int n,m,i,x,cnt,a[M],b[M],l[M],r[M],d[M];
     4 
     5 int read()
     6 {
     7     int x=0; char ch=getchar();
     8     while (ch<'0' || ch>'9') ch=getchar();
     9     while (ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    10     return x;
    11 }
    12 
    13 int main()
    14 {
    15     n=read(),m=read();
    16     for (i=1;i<=n;++i) a[i]=(b[i]=read())-b[i-1];
    17     for (i=1;i<=m;++i) d[i]=read(),a[l[i]=read()]=a[l[i]]-d[i],a[(r[i]=read())+1]=a[r[i]+1]+d[i];
    18     for (x=m,i=1;i<=n;++i)
    19         for (cnt=cnt+a[i];cnt<0;--m)
    20             if (l[m]>i) a[l[m]]=a[l[m]]+d[m],a[r[m]+1]=a[r[m]+1]-d[m];
    21             else if (r[m]>=i) cnt=cnt+d[m],a[r[m]+1]=a[r[m]+1]-d[m];
    22     if (m<x) printf("-1
    %d
    ",m+1);
    23     else printf("0
    ");
    24     return 0;
    25 }

     

  • 相关阅读:
    1539. Kth Missing Positive Number (E)
    0082. Remove Duplicates from Sorted List II (M)
    0526. Beautiful Arrangement (M)
    解决mac电脑耳机/外放突然无声音
    利用蒙特卡洛方法实现21点问题的最优解(内含python源码)
    浅析机器视觉在医疗影像处理中的应用
    基于最近邻法手写数字识别(内附python源码)
    最新版 | 2020李沐《动手学深度学习》中文版pdf重磅开源!
    干货收藏!639页《深度学习:Deep Learning》图文并茂课程PPT
    22课时、19大主题,CS 231n进阶版课程视频上线!
  • 原文地址:https://www.cnblogs.com/HHshy/p/6015457.html
Copyright © 2011-2022 走看看