线段树区间合并(模板)

Posted zhgyki

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树区间合并(模板)相关的知识,希望对你有一定的参考价值。

poj3667

技术图片
#include<cstdio>
#include<algorithm>
#define lid id << 1
#define rid id << 1 | 1
using namespace std;

const int mx = 50010;

struct tree{
    int l, r;
    int ls, rs, ms;
    int lazy;
}tree[mx<<2];

void build(int l, int r, int id){
    tree[id].l = l;
    tree[id].r = r;
    tree[id].ls = tree[id].rs = tree[id].ms = r-l+1;
    tree[id].lazy = -1;
    if (l == r) return;
    int mid = (l+r) >> 1;
    build(l, mid, lid);
    build(mid+1, r, rid);
}

void pushdown(int id){
    if (tree[id].lazy != -1){
        tree[lid].lazy = tree[rid].lazy = tree[id].lazy;
        tree[lid].ls = tree[lid].rs = tree[lid].ms = tree[id].lazy ? 0 : tree[lid].r-tree[lid].l+1;
        tree[rid].ls = tree[rid].rs = tree[rid].ms = tree[id].lazy ? 0 : tree[rid].r-tree[rid].l+1;
        tree[id].lazy = -1;
    }
}

void pushup(int id){
    tree[id].ls = tree[lid].ls;
    tree[id].rs = tree[rid].rs;
    int mid = (tree[id].l + tree[id].r) >> 1;
    if (tree[id].ls == mid-tree[id].l+1) tree[id].ls += tree[rid].ls;
    if (tree[id].rs == tree[id].r-mid) tree[id].rs += tree[lid].rs;
    tree[id].ms = max(max(tree[lid].ms, tree[rid].ms), tree[lid].rs+tree[rid].ls);
}

void upd(int l, int r, int id, bool x){
    if (tree[id].l == l && tree[id].r == r){
        tree[id].lazy = x;
        tree[id].ls = tree[id].rs = tree[id].ms = x ? 0 : r-l+1;
        return;
    }
    pushdown(id);
    int mid = (tree[id].l + tree[id].r) >> 1;
    if (r <= mid) upd(l, r, lid, x);
    else if (mid < l) upd(l, r, rid, x);
    else {
        upd(l, mid, lid, x);
        upd(mid+1, r, rid, x);
    }
    pushup(id);
}

int query(int l, int r, int id, int x){
    if (l == r) return l;
    pushdown(id);
    int mid = (l+r) >> 1;
    if (tree[lid].ms >= x) return query(l, mid, lid, x);
    else if (tree[lid].rs + tree[rid].ls >= x) return mid-tree[lid].rs+1;
    return query(mid+1, r, rid, x);
}

int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    build(1, n, 1);
    while (m--){
        int op, a, b;
        scanf("%d%d", &op, &a);
        if (op == 1){
            if (tree[1].ms < a) printf("0
");
            else {
                b = query(1, n, 1, a);
                printf("%d
", b);
                upd(b, b+a-1, 1, 1);
            }
        }
        else {
            scanf("%d", &b);
            upd(a, a+b-1, 1, 0);
        }
    }
    return 0;
}
View Code

 

以上是关于线段树区间合并(模板)的主要内容,如果未能解决你的问题,请参考以下文章

线段树区间合并(模板)

线段树区间合并POJ3667-Hotel

线段树维护区间合并——cf1285E

POJ 3368 Frequent values(线段树区间合并)

模板:启发式合并

洛谷P5494 模板线段树分裂