poj 3667 Hotel 线段树区间合并

线段树区间合并模板题
注意查询好时的操作
1. 优先查询左子树
1. 当左子树的lsum >= K 返回l
2. 返回左子树r - rsum + 1
2. 返回右子树

被 1 - N 的更新卡了好久,写篇题解记录

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX_N = 50000;
#define LC (index<<1)
#define RC (index<<1|1)
#define LSON (index<<1),(L),(mid)
#define RSON (index<<1|1),(mid+1),(R)
struct node {
    int l,r,len;
    int lsum,rsum,msum;
    int mid()
    {
        return (this->l + this->r) >> 1;
    }
};
node nodes[(MAX_N << 2) + 10];
int N,M;
void build(int index,int L,int R)
{
    nodes[index].l = L;
    nodes[index].r = R;
    nodes[index].len = R -L + 1;
    nodes[index].msum = nodes[index].lsum = nodes[index].rsum = nodes[index].len;
    if (L == R) return;
    int mid = nodes[index].mid();
    build(LSON);
    build(RSON);
}
void pushup(int index) {
    if (nodes[index].l == nodes[index].r) return;;
    nodes[index].msum = max(nodes[LC].msum,nodes[RC].msum);
    nodes[index].msum = max(nodes[index].msum,nodes[LC].rsum + nodes[RC].lsum);
    nodes[index].lsum = nodes[LC].lsum;
    if (nodes[LC].lsum == nodes[LC].len) {
        nodes[index].lsum += nodes[RC].lsum;
    }
    nodes[index].rsum = nodes[RC].rsum;
    if (nodes[RC].rsum == nodes[RC].len) {
        nodes[index].rsum += nodes[LC].rsum;
    }
}
void pushdown(int index) {
    if (nodes[index].l == nodes[index].r) return;;
    if (nodes[index].msum == nodes[index].len) {
        nodes[LC].msum = nodes[LC].lsum = nodes[LC].rsum = nodes[LC].len;
        nodes[RC].msum = nodes[RC].lsum = nodes[RC].rsum = nodes[RC].len;
    }
    if (nodes[index].msum == 0) {
        nodes[LC].msum = nodes[LC].lsum = nodes[LC].rsum = 0;
        nodes[RC].msum = nodes[RC].lsum = nodes[RC].rsum = 0;
    }
}
void leave(int index,int L,int R) {
    pushdown(index);
    if (L <= nodes[index].l && nodes[index].r <= R) {
        nodes[index].lsum = nodes[index].rsum = nodes[index].msum = nodes[index].len;
        return;
    }
    int mid = nodes[index].mid();
    if (L <= mid) leave(LC,L,R);
    if (R > mid) leave(RC,L,R);
    pushup(index);
}
void place(int index,int L,int R) {
    pushdown(index);
    if (L <= nodes[index].l && nodes[index].r <= R) {
        nodes[index].msum = nodes[index].lsum = nodes[index].rsum = 0;
        pushdown(index);
        return;
    }
    int mid = nodes[index].mid();
    if (L <= mid) place(LC,L,R);
    if (mid < R) place(RC,L,R);
    pushup(index);
}
int query(int index,int K) {
    pushdown(index);
    if (nodes[index].msum < K) {
        return 0;
    }
    if (nodes[index].l == nodes[index].r) {
        int l = nodes[index].l;
        int r = l + K - 1;
        place(index,l,r);
        return nodes[index].l;
    }
    if (nodes[LC].lsum >= K) {
        int l = nodes[index].l;
        int r = l + K - 1;
        place(index,l,r);
        pushup(index);
        return nodes[LC].l;
    }
    int ans;
    if (nodes[LC].msum >= K) {
        ans = query(LC,K);
        pushup(index);
        return ans;
    }
    if (nodes[LC].rsum != 0 && nodes[LC].rsum + nodes[RC].lsum >= K) {
        int l = nodes[LC].r - nodes[LC].rsum + 1;
        int r = l + K - 1;
        place(index,l,r);
        pushup(index);
        return l;
    }
    ans = query(RC,K);
    pushup(index);
    return ans;
}

int main()
{
    //freopen("C:\\Users\\klchen\\Desktop\\out.txt","w",stdout);
    while (~scanf("%d%d",&N,&M)) {
        build(1,1,N);
        for (int i = 0;i < M;i++) {
            int q,k,l,r;
            scanf("%d",&q);
            if (q == 1) {
                scanf("%d",&k);
                printf("%d\n",query(1,k));
            } else if (q == 2) {
                scanf("%d%d",&l,&k);
                r = l + k;
                leave(1,l,r - 1);
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值