POJ-3667 线段树区间合并入门题

Posted qaqorz

tags:

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

题意:长度为n的区间,m个操作,一开始都是0

1 x表示求出长度为x的0的连续区间的最左端,并把这个区间变成1

2 x y表示将区间[x,y]变成0

 

线段树的区间合并第一题:

每次维护左端连续区间长度ls、右端连续区间长度rs,最大连续长度ms

 

区间合并的注意点主要在push up操作:

每次更新了一段区间之后向上更新,首先,父区间的ls继承左子树的ls,父区间的rs继承右子树的rs

然后就是重点:左右区间合并之后中间部分可能是连续的!!!

所以:如果整个左、右子区间都是“满的”,父区间的ls和rs分别就要连到另一侧去

最后,父区间的ms要比较三个值:ls、rs和【左区间的rs加上右区间的ls】,这里画个图或者联系归并排序就可以看出来

 

贴一下模板以后不手敲了,怕出错

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define lid id << 1
 4 #define rid id << 1 | 1
 5 using namespace std;
 6 
 7 const int mx = 50010;
 8 
 9 struct tree{
10     int l, r;
11     int ls, rs, ms;
12     int lazy;
13 }tree[mx<<2];
14 
15 void build(int l, int r, int id){
16     tree[id].l = l;
17     tree[id].r = r;
18     tree[id].ls = tree[id].rs = tree[id].ms = r-l+1;
19     tree[id].lazy = -1;
20     if (l == r) return;
21     int mid = (l+r) >> 1;
22     build(l, mid, lid);
23     build(mid+1, r, rid);
24 }
25 
26 void pushdown(int id){
27     if (tree[id].lazy != -1){
28         tree[lid].lazy = tree[rid].lazy = tree[id].lazy;
29         tree[lid].ls = tree[lid].rs = tree[lid].ms = tree[id].lazy ? 0 : tree[lid].r-tree[lid].l+1;
30         tree[rid].ls = tree[rid].rs = tree[rid].ms = tree[id].lazy ? 0 : tree[rid].r-tree[rid].l+1;
31         tree[id].lazy = -1;
32     }
33 }
34 
35 void pushup(int id){
36     tree[id].ls = tree[lid].ls;
37     tree[id].rs = tree[rid].rs;
38     int mid = (tree[id].l + tree[id].r) >> 1;
39     if (tree[id].ls == mid-tree[id].l+1) tree[id].ls += tree[rid].ls;
40     if (tree[id].rs == tree[id].r-mid) tree[id].rs += tree[lid].rs;
41     tree[id].ms = max(max(tree[lid].ms, tree[rid].ms), tree[lid].rs+tree[rid].ls);
42 }
43 
44 void upd(int l, int r, int id, bool x){
45     if (tree[id].l == l && tree[id].r == r){
46         tree[id].lazy = x;
47         tree[id].ls = tree[id].rs = tree[id].ms = x ? 0 : r-l+1;
48         return;
49     }
50     pushdown(id);
51     int mid = (tree[id].l + tree[id].r) >> 1;
52     if (r <= mid) upd(l, r, lid, x);
53     else if (mid < l) upd(l, r, rid, x);
54     else {
55         upd(l, mid, lid, x);
56         upd(mid+1, r, rid, x);
57     }
58     pushup(id);
59 }
60 
61 int query(int l, int r, int id, int x){
62     if (l == r) return l;
63     pushdown(id);
64     int mid = (l+r) >> 1;
65     if (tree[lid].ms >= x) return query(l, mid, lid, x);
66     else if (tree[lid].rs + tree[rid].ls >= x) return mid-tree[lid].rs+1;
67     return query(mid+1, r, rid, x);
68 }
69 
70 int main(){
71     int n, m;
72     scanf("%d%d", &n, &m);
73     build(1, n, 1);
74     while (m--){
75         int op, a, b;
76         scanf("%d%d", &op, &a);
77         if (op == 1){
78             if (tree[1].ms < a) printf("0
");
79             else {
80                 b = query(1, n, 1, a);
81                 printf("%d
", b);
82                 upd(b, b+a-1, 1, 1);
83             }
84         }
85         else {
86             scanf("%d", &b);
87             upd(a, a+b-1, 1, 0);
88         }
89     }
90     return 0;
91 }

 

以上是关于POJ-3667 线段树区间合并入门题的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3667 Hotel(线段树+区间合并)

poj--3667 Hotel(线段树+区间合并)

poj3667-Hotel-线段树-区间合并

poj 3667 Hotel (线段树+区间合并)

POJ 3667 Hotel(线段树区间合并)

POJ - 3667 Hotel(线段树区间合并)