P1083 借教室

题意:给出n天可供使用的教室,给出m个订单,每个订单为一段连续的天数内使用掉相同数量的教室

   订单的处理按先来先处理原则

           问:是否能满足所有订单,假如可以的话,输出0

               假如不可以的话,就输出-1,并且输出不满足的订单的编号

思路:看到数据很容易就能想到暴力做法,但是暴力做法会超时

   所以,我们采用二分的方式,降低复杂度,最终复杂度大概为(n*logn)

   那么具体怎么做呢?我们将订单处理用一个差分数组来表示

     然后,开始二分枚举哪一次订单不满足,这是满足二分性质的

       比如:我们在第6次订单假如不满足的话,那么第七次以及后面的订单也肯定是不满足的,所以就可以在左区间二分

          假如满足的话,证明之前的订单全部合起来也都是满足情况的,所以就可以在右区间二分

     于是,知道满足二分的做法后,我们来看看如何判定

        我们取区间中点,即第mid次订单及其前面所有的订单数据,用差分数组的方式进行处理

        然后再看看有没有哪个数会出现负数

          如果有负数的情况,证明不满足,反之满足

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

 

posted @ 2020-04-10 21:41  古比  阅读(141)  评论(0编辑  收藏  举报