NOIP借教室 (线段树无脑维护区间最小值)

线段树维护的信息就是区间最小值,进行教室的订单的时候,将相应的区间减去值就可以了,然后查询区间是否出现小于0的数,出现了则不满足,即是答案。

#include <bits/stdc++.h>
#define go continue
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fory(i,a,b) for(int i = a; i <= b; ++i)
using namespace std;

template <typename T> inline void read(T& t)
{
    int f = 0, c = getchar();
    t = 0;
    while (!isdigit(c)) f |= c == '-', c = getchar();
    while (isdigit(c)) t = t * 10 + c - 48, c = getchar();
    if (f) t = -t;
}

template <typename T> void print(T x)
{
    if (x < 0) x = -x, putchar('-');
    if (x > 9) print(x / 10);
    putchar(x % 10 + 48);
}
//--------------------------------------------
const int N = 1000010;

int n, m;
int a[N];
int x, y, z;

struct node
{
    int l, r, minn, lazy;
};

struct segment_tree
{
    node t[N << 2];

    inline void push_down(int root)
    {
        if(t[root].lazy != 0)
        {
            //cal_lazy 计算lazy对当前线段的影响
            t[root].minn += t[root].lazy;
            if(t[root].l != t[root].r)

            {
                int ch = root << 1;
                //union_lazy 将lazy传递到两个子节点
                t[ch].lazy += t[root].lazy;
                t[ch + 1].lazy += t[root].lazy;
            }
            //init_lazy 清空当前lazy
            t[root].lazy = 0;
        }
    }

    inline void push_up(int root)
    {
        int ch = root << 1;
        push_down(ch);
        push_down(ch + 1);
        t[root].minn = min(t[ch].minn, t[ch + 1].minn);
    }

    inline void build(int root, int l, int r)
    {
        t[root].l = l;
        t[root].r = r;
        //init_lazy
        t[root].lazy = 0;

        if(l != r)
        {
            int ch = root << 1;
            int mid = (l + r) >> 1;
            build(ch, l, mid);
            build(ch + 1, mid + 1, r);
            push_up(root);
        }
        else t[root].minn = a[l];

    }

    inline void change(int root, int l, int r, int add)
    {
        push_down(root);

        if(t[root].l == l && t[root].r == r)
        {
            t[root].lazy += add;
            return;
        }

        int ch = root << 1;
        int mid = (t[root].l + t[root].r) >> 1;

        if(r <= mid) change(ch, l, r, add);
        else if(l > mid) change(ch + 1, l, r, add);
        else
        {
            change(ch, l, mid, add);
            change(ch + 1, mid + 1, r, add);
        }
        push_up(root);
    }

    inline int query(int root, int l, int r)
    {
        push_down(root);
        if(t[root].l == l && t[root].r == r)
        {
            return t[root].minn;
        }

        int ch = root << 1;
        int mid = (t[root].l + t[root].r) >> 1;

        if(r <= mid) return query(ch, l, r);
        else if(l > mid) return query(ch + 1, l, r);
        else return min(query(ch, l, mid), query(ch + 1, mid + 1, r));
    }
} st;


signed  main()
{
    read(n), read(m);
    fory(i, 1, n) read(a[i]);

    st.build(1, 1, n);

    fory(i, 1, m)
    {
        read(z), read(x), read(y);
        st.change(1, x, y, -z);
        int ok = st.query(1, x, y);
        if(ok < 0)
        {
            puts("-1");
            print(i);
            return 0;
        }
    }
    puts("0");


    return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值