poj1823线段树
2015-12-09 20:31
162 查看
题意:
有人要住旅馆,然后住在一些连续的房间里;
那么让你求空闲的连续的旅馆的最大长度;
理解:
此题认真想想应该就是线段树了;
然后合并的是区间,而不是单独的值;
合并区间就有点麻烦了;
主要就是两个区间合并的时候要注意中间是否可以再组成一个区间;‘
做法就是记录此区间的两端没有住人的两端;
然后将此区间的最大值求出来;
之后向上合并;
注意合并时要判断中间是否可以连接起来;
代码如下:(线段树就是太难写了,不过思路清晰就好写了)
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
#define P pair<int, int>
#define x first
#define y second
struct node
{
int len;
int flag;
P lt, rt; //左右两端的空闲区间
};
node tree[16000 * 5 + 10];
int up[16000 * 5 + 10];
node build(int l, int r, int rx)
{
if (l == r)
{
tree[rx].len = 1;
tree[rx].flag = 0;
tree[rx].lt = tree[rx].rt = P(l, r);
return tree[rx];
}
node n1 = build(l, (l + r) / 2, rx * 2);
node n2 = build((l + r) / 2 + 1, r, rx * 2 + 1);
tree[rx].len = n1.len + n2.len;
tree[rx].flag = 0;
tree[rx].lt = tree[rx].rt = P(n1.lt.x, n2.rt.y);
return tree[rx];
}
void push_down(int l, int r, int rx)
{
if (l != r)
{
up[rx * 2] = up[rx];
up[rx * 2 + 1] = up[rx];
if (up[rx] == 1)
{
tree[rx * 2].len = tree[rx * 2 + 1].len = 0;
tree[rx * 2].flag = tree[rx * 2 + 1].flag = 1;
tree[rx * 2].lt
= tree[rx * 2].rt
= tree[rx * 2 + 1].lt
= tree[rx * 2 + 1].rt
= P(-1, -1);
}
else
{
tree[rx * 2].len
= (l + r) / 2 - l + 1;
tree[rx * 2 + 1].len
= r - (l + r) / 2 - 1 + 1;
tree[rx * 2].flag = tree[rx * 2 + 1].flag = 0;
tree[rx * 2].lt
= tree[rx * 2].rt
= P(l, (l + r) / 2);
tree[rx * 2 + 1].lt
= tree[rx * 2 + 1].rt
= P((l + r) / 2 + 1, r);
}
}
up[rx] = 0;
}
void update(int l, int r, int L, int R, int rx, int num)
{
if (L > r || R < l) return ;
if (L >= l && R <= r)
{
up[rx] = (num == 0 ? -1 : 1);
if (num == 0)
{
tree[rx].len = R - L + 1;
tree[rx].flag = 0;
tree[rx].lt = tree[rx].rt = P(L, R);
}
else
{
tree[rx].len = 0;
tree[rx].flag = 1;
tree[rx].lt = tree[rx].rt = P(-1, -1);
}
return ;
}
if (up[rx])
{
push_down(L, R, rx); //开始的时候push_down放错位置了,结果超时,坑
}
update(l, r, L, (L + R) / 2, rx * 2, num);
node n1 = tree[rx * 2];
update(l, r, (L + R) / 2 + 1, R, rx * 2 + 1, num);
node n2 = tree[rx * 2 + 1];
if (n1.flag != n2.flag)
{
tree[rx] = (n1.flag == 0 ? n1 : n2);
return ;
}
if (n1.flag == n2.flag && n1.flag == 1)
{
tree[rx].len = 0;
tree[rx].flag = 1;
tree[rx].lt = tree[rx].rt = P(-1, -1);
return ;
}
if (n1.rt.y + 1 == n2.lt.x)
{
tree[rx].len = max(n1.len, max(n2.len, n2.lt.y - n1.rt.x + 1));
tree[rx].flag = 0;
if (n1.lt.y < n1.rt.x)
{
tree[rx].lt = n1.lt;
}
else tree[rx].lt = P(n1.rt.x, n2.lt.y);
if (n2.lt.y < n2.rt.x)
{
tree[rx].rt = n2.rt;
}
else tree[rx].rt = P(n1.rt.x, n2.lt.y);
return ;
}
tree[rx].len = max(n1.len, n2.len);
tree[rx].flag = 0;
tree[rx].lt = n1.lt;
tree[rx].rt = n2.rt;
return ;
}
int main()
{
int n, p;
scanf("%d%d", &n, &p);
build(1, n, 1);
for (int i = 0; i < p; ++i)
{
int num;
scanf("%d", &num);
if (num == 3)
{
printf("%d\n", tree[1].len);
}
else if (num == 1)
{
int num1, num2;
scanf("%d%d", &num1, &num2);
update(num1, num1 + num2 - 1, 1, n, 1, 1);
}
else
{
int num1, num2;
scanf("%d%d", &num1, &num2);
update(num1, num1 + num2 - 1, 1, n, 1, 0);
}
}
return 0;
}
有人要住旅馆,然后住在一些连续的房间里;
那么让你求空闲的连续的旅馆的最大长度;
理解:
此题认真想想应该就是线段树了;
然后合并的是区间,而不是单独的值;
合并区间就有点麻烦了;
主要就是两个区间合并的时候要注意中间是否可以再组成一个区间;‘
做法就是记录此区间的两端没有住人的两端;
然后将此区间的最大值求出来;
之后向上合并;
注意合并时要判断中间是否可以连接起来;
代码如下:(线段树就是太难写了,不过思路清晰就好写了)
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
#define P pair<int, int>
#define x first
#define y second
struct node
{
int len;
int flag;
P lt, rt; //左右两端的空闲区间
};
node tree[16000 * 5 + 10];
int up[16000 * 5 + 10];
node build(int l, int r, int rx)
{
if (l == r)
{
tree[rx].len = 1;
tree[rx].flag = 0;
tree[rx].lt = tree[rx].rt = P(l, r);
return tree[rx];
}
node n1 = build(l, (l + r) / 2, rx * 2);
node n2 = build((l + r) / 2 + 1, r, rx * 2 + 1);
tree[rx].len = n1.len + n2.len;
tree[rx].flag = 0;
tree[rx].lt = tree[rx].rt = P(n1.lt.x, n2.rt.y);
return tree[rx];
}
void push_down(int l, int r, int rx)
{
if (l != r)
{
up[rx * 2] = up[rx];
up[rx * 2 + 1] = up[rx];
if (up[rx] == 1)
{
tree[rx * 2].len = tree[rx * 2 + 1].len = 0;
tree[rx * 2].flag = tree[rx * 2 + 1].flag = 1;
tree[rx * 2].lt
= tree[rx * 2].rt
= tree[rx * 2 + 1].lt
= tree[rx * 2 + 1].rt
= P(-1, -1);
}
else
{
tree[rx * 2].len
= (l + r) / 2 - l + 1;
tree[rx * 2 + 1].len
= r - (l + r) / 2 - 1 + 1;
tree[rx * 2].flag = tree[rx * 2 + 1].flag = 0;
tree[rx * 2].lt
= tree[rx * 2].rt
= P(l, (l + r) / 2);
tree[rx * 2 + 1].lt
= tree[rx * 2 + 1].rt
= P((l + r) / 2 + 1, r);
}
}
up[rx] = 0;
}
void update(int l, int r, int L, int R, int rx, int num)
{
if (L > r || R < l) return ;
if (L >= l && R <= r)
{
up[rx] = (num == 0 ? -1 : 1);
if (num == 0)
{
tree[rx].len = R - L + 1;
tree[rx].flag = 0;
tree[rx].lt = tree[rx].rt = P(L, R);
}
else
{
tree[rx].len = 0;
tree[rx].flag = 1;
tree[rx].lt = tree[rx].rt = P(-1, -1);
}
return ;
}
if (up[rx])
{
push_down(L, R, rx); //开始的时候push_down放错位置了,结果超时,坑
}
update(l, r, L, (L + R) / 2, rx * 2, num);
node n1 = tree[rx * 2];
update(l, r, (L + R) / 2 + 1, R, rx * 2 + 1, num);
node n2 = tree[rx * 2 + 1];
if (n1.flag != n2.flag)
{
tree[rx] = (n1.flag == 0 ? n1 : n2);
return ;
}
if (n1.flag == n2.flag && n1.flag == 1)
{
tree[rx].len = 0;
tree[rx].flag = 1;
tree[rx].lt = tree[rx].rt = P(-1, -1);
return ;
}
if (n1.rt.y + 1 == n2.lt.x)
{
tree[rx].len = max(n1.len, max(n2.len, n2.lt.y - n1.rt.x + 1));
tree[rx].flag = 0;
if (n1.lt.y < n1.rt.x)
{
tree[rx].lt = n1.lt;
}
else tree[rx].lt = P(n1.rt.x, n2.lt.y);
if (n2.lt.y < n2.rt.x)
{
tree[rx].rt = n2.rt;
}
else tree[rx].rt = P(n1.rt.x, n2.lt.y);
return ;
}
tree[rx].len = max(n1.len, n2.len);
tree[rx].flag = 0;
tree[rx].lt = n1.lt;
tree[rx].rt = n2.rt;
return ;
}
int main()
{
int n, p;
scanf("%d%d", &n, &p);
build(1, n, 1);
for (int i = 0; i < p; ++i)
{
int num;
scanf("%d", &num);
if (num == 3)
{
printf("%d\n", tree[1].len);
}
else if (num == 1)
{
int num1, num2;
scanf("%d%d", &num1, &num2);
update(num1, num1 + num2 - 1, 1, n, 1, 1);
}
else
{
int num1, num2;
scanf("%d%d", &num1, &num2);
update(num1, num1 + num2 - 1, 1, n, 1, 0);
}
}
return 0;
}
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- 线段树题集
- POJ ACM 1001
- POJ ACM 1002
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- 用单调栈解决最大连续矩形面积问题
- 2632 Crashing Robots的解决方法
- 1573 Robot Motion (简单题)
- POJ 1200 Crazy Search(简单哈希)
- 【高手回避】poj3268,一道很水的dijkstra算法题
- POJ 1088 滑雪