[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\n%d\n",k);
33     else printf("0\n");
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\n%d\n",m+1);
23     else printf("0\n");
24     return 0;
25 }
时间: 2024-10-26 02:52:43

[NOIP2012]借教室 题解的相关文章

浅谈差分数组的应用(二)&amp;[NOIP2012]借教室题解

[NOIP2012提高&洛谷P1083]借教室 Description 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样.面对海量租借教室的信息,我们自然希望编程解决这个问题. 我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要

NOIP2012借教室[线段树|离线 差分 二分答案]

题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然希望编程解决这个问题. 我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份 订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租 借教室(包括第sj天和第tj天),每天需要租借dj个教室. 我们假定,租借者对教室的大小.地点没

洛谷 P1083 借教室 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1083 题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然希望编程解决这个问题. 我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份订单,每份订单用三个正整数描

NOIP2012 借教室 Splay初探

终于把区间操作的Splay搞明白了…… Splay的大致框架是这样的: 1 template <class T> 2 struct SplayNode 3 { 4 typedef SplayNode<T> Node; 5 Node* lch; 6 Node* rch; 7 Node* parent; 8 T val; 9 10 SplayNode(const T& _val,Node* _parent): 11 lch(0),rch(0),parent(_parent),v

noip2012借教室

Description Input Output Sample Input 4 3 2 5 4 3 2 1 3 3 2 4 4 2 4 Sample Output -1 2 Data Constraint Hint 第一份订单满足后,4天剩余教室分数分别为0,3,2,3. 第二份订单要求第二天到第四天每天提供三个教室,而第三天剩余的教室数为二,因此无法满足.分配停止通知第二个申请人修改订单. 10% -> 1<=n,m<=10 30% -> 1<=n,m<=1000 7

NOIP2012 借教室

自己YY出来的方法,时间复杂度为n*m,但实际上并没有这么多,codeVS上最慢的一组有300多ms. 对于每一个订单,在它的左端点加上需要的教室数量,在右端点加1的位置减去需要的教室数量.然后统计前缀和,如果有某个点的前缀和大于了当天教室的数量,那么就有的订单就有问题了,然后从订单编号从小到大统计在订单区间的教室数量,保存恰好不能满足的那个订单:对于之后不满足题意的前缀和,统计订单的最大编号不能超过之前保存的订单标号. #include<cstdio> #define MAXN 100000

【差分序列】【NOIP2012】借教室

1266. [NOIP2012] 借教室 ★★☆ 输入文件:classrooms.in 输出文件:classrooms.out 简单对比 时间限制:1 s 内存限制:128 MB [题目描述] 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然希望编程解决这个问题. 我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份 订单,每

【NOIP2012】借教室

在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然希望编程解决这个问题. 我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份 订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租 借教室(包括第sj天和第tj天),每天需要租借dj个教室. 我们假定,租借者对教室的大小.地点没有要求.即

【题解】CODEVS 1217 借教室 zkw线段树(区间最值)

捣鼓了好长时间才终于把zkw线段树的区间最值修改给A掉了 = =zkw神犇的课件里竟然有错! (╯▽╰)下面的伪代码里被注释的是我修改的>< Func Add_x(s,t,x) for (s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1) { if (~s&1) T[s^1]+=x; if ( t&1) T[t^1]+=x; A=min(T[s],T[s^1]),T[s]-=A,T[s^1]-=A, T[s>>1]+=A;