[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 }
成功做完关于classroom的题目:NOIP2012D2T2借教室,NOIP2016D1T3换教室......