HDU - 4553 线段树区间合并

线段树区间合并, 三种命令, D t: 请求一段长度为t的连续区间, 返回区间开始位置; N t: 同上, 但如果没有符合要求, 则忽略之前D的请求再寻找; S t1, t2: 清空[t1, t2];

维护两个区间合并的线段树, 因为两个线段树功能都是一样的, 所以不需要写双份的代码了, 函数增加一个参数用以表示是哪个线段树;

太久没写了, 写完后WA了, 因为一个rt手抖写成了rt<<1, 一个地方少写了一个update, t是线段树的大小, 但一不小心习惯性地把n当成了线段树大小…一大堆这种错误, 改了好久, 太不熟练了

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

#define ls l, m, rt<<1
#define rs m+1, r, rt<<1|1
#define defm int m = (l+r)>>1
const int MAXN = 1e6 + 1000;
int T, t, n, a, b, c;
struct P { int lsum, rsum, msum, color; };
P ds[MAXN<<2], ns[MAXN<<2];
char op[19];

void pushUp(P p[], int rt, int m)
{
    p[rt].lsum = p[rt<<1].lsum;
    if(p[rt<<1].lsum == (m-(m>>1))) p[rt].lsum += p[rt<<1|1].lsum;
    p[rt].rsum = p[rt<<1|1].rsum;
    if(p[rt<<1|1].rsum == (m>>1)) p[rt].rsum += p[rt<<1].rsum;
    p[rt].msum = max(p[rt<<1].msum, max(p[rt<<1|1].msum, p[rt<<1].rsum+p[rt<<1|1].lsum) );
}

void pushDown(P p[], int rt, int m)
{
    if(p[rt].color!=-1)
    {
        p[rt<<1].color = p[rt<<1|1].color = p[rt].color;
        p[rt<<1].lsum = p[rt<<1].msum = p[rt<<1].rsum = p[rt].color ? 0 : m-(m>>1);
        p[rt<<1|1].lsum = p[rt<<1|1].msum = p[rt<<1|1].rsum = p[rt].color ? 0 : (m>>1);
        p[rt].color = -1;
    }
}

void build(P p[], int l, int r, int rt)
{
    p[rt].color = -1;
    p[rt].lsum = p[rt].msum = p[rt].rsum = r-l+1;
    if(l==r) return;
    defm;
    build(p, ls);
    build(p, rs);
}

int query(P p[], int v, int l, int r, int rt)
{
    if(v > p[rt].msum) return 0;
    if(l==r) return l;
    pushDown(p, rt, r-l+1);
    defm;
    if(p[rt<<1].msum >= v) return query(p, v, ls);
    if(p[rt<<1].rsum + p[rt<<1|1].lsum >= v) return m - p[rt<<1].rsum + 1;
    return query(p, v, rs);
}

void update(P p[], int L, int R, int o, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        p[rt].color = o;
        p[rt].lsum = p[rt].msum = p[rt].rsum = o ? 0 : (r-l+1);
        return;
    }
    if(R < l || r < L) return;
    pushDown(p, rt, r-l+1);
    defm;
    update(p, L, R, o, ls);
    update(p, L, R, o, rs);
    pushUp(p, rt, r-l+1);
}

int main()
{
    scanf("%d", &T);
    for(int cas = 1; cas <= T; ++cas)
    {
        printf("Case %d:\n", cas);
        scanf("%d%d", &t, &n);
        build(ds, 1, t, 1);
        build(ns, 1, t, 1);
        for(int i=0; i<n; ++i)
        {
            scanf("%s%d", op, &a);
            if(op[0] == 'D')
            {
                b = query(ds, a, 1, t, 1);
                if(b)
                {
                    printf("%d,let's fly\n", b);
                    update(ds, b, b+a-1, 1, 1, t, 1);
                }
                else printf("fly with yourself\n");
            }
            else if(op[0] == 'N')
            {
                b = query(ds, a, 1, t, 1);
                if(b)
                {
                    printf("%d,don't put my gezi\n", b);
                    update(ds, b, b+a-1, 1, 1, t, 1);
                    update(ns, b, b+a-1, 1, 1, t, 1);
                }
                else
                {
                    c = query(ns, a, 1, t, 1);
                    if(c)
                    {
                        printf("%d,don't put my gezi\n", c);
                        update(ns, c, c+a-1, 1, 1, t, 1);
                        update(ds, c, c+a-1, 1, 1, t, 1);
                    }
                    else printf("wait for me\n");
                }
            }
            else
            {
                scanf("%d", &b);
                update(ds, a, b, 0, 1, t, 1);
                update(ns, a, b, 0, 1, t, 1);
                printf("I am the hope of chinese chengxuyuan!!\n");
            }
        }
    }
    return 0;
}

Written with StackEdit.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值