不用二分的借教室
Posted cc123321
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不用二分的借教室相关的知识,希望对你有一定的参考价值。
在网上一直看到用二分做的借教室,说什么线段树会惨遭TLE,然后我就试了一下,并没有什么事情发生(或许是因为optimizi(2)...),但并没有什么关系!!!
我们只需要在每个树的节点上打上mi的标记,表示其子树的最小值,在更新的时候如果mi小于0,就知道不行了,标记一下直接输出就好了。。。
详见代码:
#include<bits/stdc++.h> #pragma GCC optimize(2) #define in1(x) scanf("%d",&x) #define in3(x,y,z) scanf("%d%d%d",&x,&y,&z) using namespace std; int a[4000000],n,m,k,x,y,day,shu,f,val; struct st{ int l,r,val,add,mi; }tr[4000000]; void build(int l,int r,int k) { tr[k].l = l; tr[k].r = r; if(l==r) { tr[k].val = a[l]; tr[k].mi = tr[k].val; return; } int mid = (l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); tr[k].val = tr[k<<1].val + tr[k<<1|1].val; tr[k].mi = min(tr[k<<1].mi , tr[k<<1|1].mi); } void push(int k) { int l = tr[k].l , r = tr[k].r; int w = tr[k>>1].add; tr[k].val += (r-l+1)*w; tr[k].add += w; tr[k].mi -= w; } int update(int x,int y,int k,int val) { int l = tr[k].l , r = tr[k].r; if(tr[k].add) { push(k<<1); push(k<<1|1); tr[k].add = 0; } if(y<l || r<x) return 0; if(x<=l && r<=y) { tr[k].add += val; tr[k].val -= (r-l+1)*val; tr[k].mi -=val; if(tr[k].mi < 0) f=1; return 0; } int mid = (l+r)>>1; if(x<=mid) update(x,y,k<<1,val); if(y>mid) update(x,y,k<<1|1,val); tr[k].mi = min(tr[k<<1].mi , tr[k<<1|1].mi); if(tr[k].mi < 0) f=1; return 0; } main(){ in1(k); in1(shu); for(int i=1;i<=k;i++) in1(a[i]); build(1,k,1); for(int i=1;i<=shu;i++) { in3(day,x,y); val=day; update(x,y,1,val); if(f==1) { printf("-1\n%d",i); return 0; } } printf("0"); }
以上是关于不用二分的借教室的主要内容,如果未能解决你的问题,请参考以下文章