【NOIP2012-Day2-T2-换教室】

题目lk

好吧D2T2考线段树还行。

其实是不考的。

题目大意就是给一个区间$[l,r]$,然后让这个区间减掉$d$,这样算一次操作

然后给你$m$次操♂作,求第几次操作之后开始出现负数。

显然线段树乱搞是可以AC的。

但是我们深知2012年的出题人还没有那么毒瘤。

于是我们发现,这个问题是满足单调性的。

也就是说,第$i$次操作如果有负数,那么$i+1$次也有

同理$i$没有那么$i-1$也没有

所以是一道二分,然后每次判断的时候用差分维护一下,就顺利AC了

代码(吼吼,check♂it♂out)

 

 1 #include<bits/stdc++.h>
 2 #define maxn (1000000+500)
 3 using namespace std;
 4 int n,m;
 5 int r[maxn],d[maxn];
 6 int s[maxn],t[maxn];
 7 int del[maxn];
 8 
 9 int check(int N)
10 {
11     memset(del,0,sizeof(del));
12     for (int i=1;i<=N;++i)
13     {
14         del[s[i]]+=d[i];
15         del[t[i]+1]-=d[i];
16     }
17     int now=0;
18     for (int i=1;i<=n;++i)
19     {
20         now+=del[i];
21         if (now>r[i]) return 0;
22     }
23     return 1;
24 }  
25 
26 int main()
27 {
28     scanf("%d%d",&n,&m);
29     for (int i=1;i<=n;++i) scanf("%d",&r[i]);
30     for (int i=1;i<=m;++i)
31         scanf("%d%d%d",&d[i],&s[i],&t[i]);
32     
33     int ans=0,l=0,r=n;
34     while (l<=r)
35     {
36         int mid=(l+r)>>1;
37         if (check(mid))
38         {
39             ans=mid;
40             l=mid+1;
41         }
42         else r=mid-1;
43     }
44     
45     if (ans==n) puts("0");
46     else printf("-1\n%d\n",ans+1);
47     
48     return 0;
49 }

 

好吧要是写线段树可能思维难度更低

 

posted @ 2019-03-30 21:40  曦行夜落  阅读(154)  评论(0编辑  收藏  举报