[NOIP2016]借教室

NOIP2012提高组D2T2。

这道题目非常基础,正解貌似是二分+差分数组,在这里提供一种线段树的思路。

很容易发现题目让我们每次修改一段区间,然后我们只需要看每一个区间内有没有负数就可以了。可以用线段树维护每个区间内的最小值,修改的话就直接减就可以了,不要忘了标记下放(否则只有5分...)最后查看1-n内最小值是否为负数即可。

参考代码如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #define mid (l+r)/2
 6 #define lc k*2
 7 #define rc k*2+1
 8 using namespace std;
 9 int read()
10 {
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
13     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14     if(f)return x;return -x; 
15 }
16 struct node
17 {
18     int l,r,tag,w;
19 }tree[4000005];
20 int n,m,x,y,val,num;
21 void pushup(int k){tree[k].w=min(tree[lc].w,tree[rc].w);}
22 void build(int l,int r,int k)
23 {
24     tree[k].l=l;tree[k].r=r;
25     if(l==r){tree[k].w=read();return;}
26     build(l,mid,lc);build(mid+1,r,rc);
27     pushup(k);
28 }
29 void pushdown(int k)
30 {
31     tree[lc].tag+=tree[k].tag;tree[rc].tag+=tree[k].tag;
32     tree[lc].w-=tree[k].tag;tree[rc].w-=tree[k].tag;
33     tree[k].tag=0;
34 }
35 void add(int k)
36 {
37     int l=tree[k].l,r=tree[k].r;
38     if(l>=x&&r<=y)
39     {
40         tree[k].w-=val;
41         tree[k].tag+=val;
42         if(tree[k].w<0)
43         {
44             cout<<-1<<endl<<num<<endl;
45             exit(0);
46         }
47         return;
48     }
49     if(tree[k].tag)pushdown(k);
50     if(x<=mid)add(lc);
51     if(y>mid)add(rc);
52     pushup(k);
53 }
54 int main()
55 {
56     //freopen("classroom.in","r",stdin);
57     //freopen("classroom.out","w",stdout);
58     n=read();m=read();
59     build(1,n,1);
60     for(int i=1;i<=m;i++)
61     {
62         num=i;val=read();x=read();y=read();
63         add(1);
64     }
65     cout<<0<<endl;
66     //fclose(stdin);
67     //fclose(stdout);
68     return 0;
69 }
View Code

成功做完关于classroom的题目:NOIP2012D2T2借教室,NOIP2016D1T3换教室......

猜你喜欢

转载自www.cnblogs.com/szmssf/p/11297240.html
今日推荐