当前位置: 代码迷 >> 综合 >> poj 3667 (线段树区间合并)
  详细解决方案

poj 3667 (线段树区间合并)

热度:98   发布时间:2023-12-23 11:11:19.0

 区间合并建线段树用结构体方便,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);elsereturn 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;
}