[数据结构]线段树

区间修改区间和:

#include<stdio.h>
#include<algorithm>
#define maxn 50005
using namespace std;
ll a[maxn << 2], lazy[maxn << 2], n;
void pushup(int k){ a[k] = a[k << 1] + a[k << 1 | 1]; }
void pushdown(int k, int m)
{
    if (lazy[k]){
    lazy[k << 1] += lazy[k];
    lazy[k << 1 | 1] += lazy[k];
    a[k << 1] += (m - (m >> 1)) * lazy[k];
    a[k << 1 | 1] +=  (m >> 1) * lazy[k];
    lazy[k] = 0;
    }
}
void build(int k, int l, int r)
{
    if (l == r){
        scanf("%d", &a[k]);
        return ;
    }
    int m = (l + r) >> 1;
    build(k << 1, l, m);
    build(k << 1 | 1, m + 1, r);
    pushup(k);
}
void update(int k, int l, int r, int x, int y, int v)
{
    if (x <= l && r <= y){
        lazy[k] += v;
        a[k] += v * (r - l + 1);
        return ;
    }
    pushdown(k, r - l + 1);
    int m = (l + r) >> 1;
    if (x <= m) update(k << 1, l, m, x, y, v);
    if (m < y) update(k << 1 | 1, m + 1, r, x, y, v);
    pushup(k);
}
ll query(int k, int l, int r, int x, int y)
{
    if(x <= l && r <= y) return a[k];
    pushdown(k, r - l + 1);
    ll res = 0, m = (l + r) >> 1;
    if (x <= m) res += query(k << 1, l, m, x, y);
    if (m < y) res += query(k << 1 | 1, m + 1, r, x, y);
    return res;
}

单点修改区间最大值

#include<stdio.h>
#include<algorithm>
using namespace std;
#define maxn 200005
int n, m;
int a[maxn << 2], lazy[maxn << 2];
void pushup(int k){ a[k] = max(a[k << 1], a[k << 1 | 1]); }
void build(int k, int l, int r)
{
    if (l == r){
        scanf("%d", &a[k]);
        return ;
    }
    int m = (l + r) >> 1;
    build(k << 1, l, m);
    build(k << 1 | 1, m + 1, r);
    pushup(k);
}
void update(int k, int l, int r, int x, int v)
{
    if (l == r){
        a[k] = v;
        return ;
    }
    int m = (l + r) >> 1;
    if (x <= m) update(k << 1, l, m, x, v);
    else update(k << 1 | 1, m + 1, r, x, v);
    pushup(k);
}
int query(int k, int l, int r, int x, int y)
{
    if (x <= l && r <= y) return a[k];
    int m = (l + r) >> 1, res = 0;
    if (x <= m) res = max(res, query(k << 1, l, m, x, y));
    if (m < y) res = max(res, query(k << 1 | 1, m + 1, r, x, y));
    return res;
}

POJ – 3667 – Hotel(线段树区间合并)
http://poj.org/problem?id=3667

#include<stdio.h>
#include<algorithm>
#define maxn 50005
using namespace std;
struct e{
    int sum, ls, rs, tag;
}a[maxn << 2];
void pushup(int k, int d)
{
    int l = k << 1, r = k << 1 | 1;
    a[k].ls = a[l].ls, a[k].rs = a[r].rs;
    if (a[k].ls == d - d / 2) a[k].ls += a[r].ls;
    if (a[k].rs == d / 2) a[k].rs += a[l].rs;
    a[k].sum = max(a[l].rs + a[r].ls, max(a[l].sum, a[r].sum));
    return ;
}
void pushdown(int k, int d)
{
    if (a[k].tag){
        int l = k << 1, r = k << 1 | 1;
        a[l].tag = a[r].tag = a[k].tag;
        a[l].ls = a[l].rs = a[l].sum = a[k].tag > 0 ? 0 : d - d / 2;
        a[r].ls = a[r].rs = a[r].sum = a[k].tag > 0 ? 0 : d / 2;
        a[k].tag = 0;
    }
    return ;
}
void build(int k, int l, int r)
{
    a[k].sum = a[k].ls = a[k].rs = r - l + 1;
    if (l == r) return ;
    int m = (l + r) >> 1;
    build(k << 1, l, m);
    build(k << 1 | 1, m + 1, r);
    return ;
}
void update(int k, int l, int r, int x, int y, int c)
{
    if (x <= l && r <= y){
        a[k].ls = a[k].rs = a[k].sum = c > 0 ? 0 : r - l + 1;
        a[k].tag = c;
        return ;
    }
    pushdown(k, r - l + 1);
    int m = (l + r) >> 1;
    if (x <= m) update(k << 1, l, m, x, y, c);
    if (m < y) update(k << 1 | 1, m + 1, r, x, y, c);
    pushup(k, r - l + 1);
    return ;
}
int query(int k, int l, int r, int d)
{
    if (l == r) return 1;
    pushdown(k, r - l + 1);
    int m = (l + r) >> 1;
    if (a[k << 1].sum >= d) return query(k << 1, l, m, d);
    if (a[k << 1].rs + a[k << 1 | 1].ls >= d) return m - a[k << 1].rs + 1;
    return query(k << 1 | 1, m + 1, r, d);
}
int main()
{
    int n, m, p, x, d, pos;
    scanf("%d %d", &n, &m);
    build(1, 1, n);
    while (m--){
        scanf("%d", &p);
        if (p == 1){
            scanf("%d", &d);
            if (d > a[1].sum){
                puts("0");
                continue;
            }
            pos = query(1, 1, n, d);
            update(1, 1, n, pos, pos + d - 1, 1);
            printf("%d\n", pos);
        }else{
            scanf("%d %d", &x, &d);
            update(1, 1, n, x, x + d - 1, -1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值