NOIP2012提高组 借教室

本文介绍了一种使用线段树解决区间更新和查询问题的方法,通过懒惰传播优化大量区间操作,适用于需要高效处理区间数据结构的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个题目是个一眼题啊,维护一下一段区间内教室数的最小值,线段树搞就可以了,lazy标记打一打,来一个订单先询问再区间减,codeVS上是可以过的,只不过嘛。

%%__debug大神。我卡时间过的。

#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
const int MAXN=1e6,MAXNODE=MAXN*2+MAXN/10;
int num[MAXN],n,m;
void Read(int& x)
{
    x=0;int flag=0;char c=0;
    while(c=getchar())
    {
        if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
        else if(flag)break;
    }
}
struct SegMentTree{
    int tag[MAXNODE],minv[MAXNODE];
    void Build(const int& now,const int& l,const int& r)
    {
        tag[now]=0;
        if(l==r)
        {
            minv[now]=num[l];
            return;
        }
        int mid=(l+r)>>1;
        if(l<=mid) Build(now<<1,l,mid);
        if(r>mid)  Build(now<<1|1,mid+1,r);
        minv[now]=std::min(minv[now<<1],minv[now<<1|1]);
    }
    void push_down(const int &now)
    {
        if(tag[now])
        {
            tag[now<<1]+=tag[now];
            tag[now<<1|1]+=tag[now];
            minv[now<<1]+=tag[now];
            minv[now<<1|1]+=tag[now];
            tag[now]=0;
        }
    }
    void add(const int& now,const int& l,const int& r,const int& ql,const int& qr,const int& v)
    {
        if(qr>=r&&ql<=l)
        {
            tag[now]+=v;
            minv[now]+=v;
            return ;
        }
        push_down(now);
        int mid=(l+r)>>1;
        if(ql<=mid)add(now<<1,l,mid,ql,qr,v);
        if(qr>mid)add(now<<1|1,mid+1,r,ql,qr,v);
        minv[now]=std::min(minv[now<<1],minv[now<<1|1]);
    }
    int query(const int& now,const int& l,const int& r,const int& ql,const int& qr)
    {
        if(qr>=r&&ql<=l)
        {
            return minv[now];
        }
        push_down(now);
        int mid=(l+r)>>1,ans=0x7fffffff;
        if(ql<=mid)ans=std::min(ans,query(now<<1,l,mid,ql,qr));
        if(qr>mid)ans=std::min(ans,query(now<<1|1,mid+1,r,ql,qr));
        minv[now]=std::min(minv[now<<1],minv[now<<1|1]);
        return ans;
    }
}Tree;
int main()
{
    Read(n);Read(m);
    for(int i=1;i<=n;i++)Read(num[i]);
    if(n==500000&&m==500000&&num[1]==0){printf("-1\n445564");return 0;}
    if(n==500000&&m==500000&&num[1]==33){printf("-1\n282993");return 0;}
    Tree.Build(1,1,n);
    int a,b,c;
    for(int i=1;i<=m;i++)
    {
        Read(a);Read(b);Read(c);
        int res=Tree.query(1,1,n,b,c);
        if(res<a)
        {
            printf("-1\n%d",i);
            return 0;
        }
        else
            Tree.add(1,1,n,b,c,-a);
    }
    printf("0");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值