poj 3667 区间合并基础题

 区间合并建线段树用结构体方便,build时不需要pushup(小特点~),而且结构体内置函数省下好多代码量,(据说是某巨佬HH的风格)。最重要的一点,pushup时当左/右子节点全部长度可用时(说明和另一方相连了),需要更新父节点的llen和rrlen。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 5e4 + 10;

struct Tree
{
    int l, r;
    int len;
    int llen, rlen;
    int mark;

    int mid()
    {
        return l + r >> 1;
    }
    int cal_len()
    {
        return r - l + 1;
    }
    void update_len()
    {
        len = llen = rlen = (mark ? 0 : cal_len());
    }
}tree[maxn << 2];
int n, m;


void build(int rt, int l, int r)
{
    tree[rt].l = l, tree[rt].r = r;
    tree[rt].mark = 0;                          //take care!
    tree[rt].cal_len();
    if(l == r)
    {
        return;
    }

    int mid = l + r >> 1;
    build(rt << 1, l, mid);
    build(rt << 1|1, mid + 1, r);
    //tree[rt].len = tree[rt].llen = tree[rt].rlen = tree[rt << 1].len + tree[rt << 1|1].len;
}


void pushdown(int rt)
{
    tree[rt << 1].mark = tree[rt << 1|1].mark = tree[rt].mark;
    tree[rt].mark = -1;
    tree[rt << 1].update_len();
    tree[rt << 1|1].update_len();
}


int query(int rt, int l, int r, int w)
{

    if(tree[rt].mark != -1)
        pushdown(rt);

    int mid = l + r >> 1;
    if(tree[rt << 1].len >= w)
        return query(rt << 1, l, mid, w);
    else if(tree[rt << 1].rlen + tree[rt << 1|1].llen >= w)
        return (tree[rt << 1].r - tree[rt << 1].rlen + 1);
    else if(tree[rt << 1|1].len >= w)
        return query(rt << 1|1, mid + 1, r, w);
    else
        return 0;
}



void update(int rt, int ql, int qr, int val)
{
    if(ql <= tree[rt].l && tree[rt].r <= qr)
    {
        tree[rt].mark = val;
        tree[rt].update_len();
        return;
    }
    if(tree[rt].mark != -1)
        pushdown(rt);

    int mid = tree[rt].mid();
    if(qr <= mid)
        update(rt << 1, ql, qr, val);
    else if(ql > mid)
        update(rt << 1|1, ql, qr, val);
    else
    {
        update(rt << 1, ql, mid, val);
        update(rt << 1|1, mid + 1, qr, val);
    }
    int tmp = max(tree[rt << 1].len , tree[rt << 1|1].len);
    tmp = max(tmp, tree[rt << 1].rlen + tree[rt << 1|1].llen);
    tree[rt].len = tmp;
    tree[rt].llen = tree[rt << 1].llen;
    tree[rt].rlen = tree[rt << 1|1].rlen;
    if(tree[rt << 1].len == tree[rt << 1].cal_len())
        tree[rt].llen += tree[rt << 1|1].llen;
    if(tree[rt << 1|1].len == tree[rt << 1|1].cal_len())
        tree[rt].rlen += tree[rt << 1].rlen;
}


int main()
{
    cin >> n >> m;
    build(1, 1, n);
    int a, b, c;
    for(int i = 0; i < m; i++)
    {
        cin >> a;
        if(a == 1)
        {
            cin >> b;
            int ans = query(1, 1, n, b);
            cout << ans << endl;
            if(ans)
                update(1, ans, ans + b - 1, 1);
        }
        else
        {
            cin >> b >> c;
            update(1, b, b + c - 1, 0);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38577732/article/details/89198185