不用二分的借教室

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");
}

 

以上是关于不用二分的借教室的主要内容,如果未能解决你的问题,请参考以下文章

借教室 差分+二分答案

借教室 线段树and二分

差分+二分答案NOIP2012借教室

Luogu 1083NOIP2012借教室二分答案

NOIP2012借教室[线段树|离线 差分 二分答案]

Luogu P1083 借教室二分答案/差分By cellur925