【题目描述】
先是在数轴区间 0 到10^9 (10的9次方)之间画上了白色。然后,这个区间的某一些部分又画上了黑色。然后某一些部分又画上白色,等等。请你找出经历M(1 <= M <= 5000)次重着色后,最长的白色区间。
【输入格式】
首行位N,以下N行位重着色的信息,每一行格式如下:ai bi ci 这里 ai ,bi 都是整数, ci 为字符'b' 或'w',用空格隔开。这三个参数描述:从ai到bi,着颜色ci, ('w'表示白,'b'表示黑),可以认为0 < ai <= bi < 10^9
【输出格式】
输出x,y (x < y)之间用空格隔开,表示最长的白色区间。假如有多个答案输出x最小的那个。
Sample Input4
1 999999997 b
40 300 w
300 634 w
43 47 b
47 634
Solution
很经典的离散化线段树。列几个坑点:
①以段建树要注意好区间开闭
②不要忘记0和1000000000这两个端点
③长度最大是按离散化前的长度定义的
Code
#include <cstdio>
#include <algorithm>
#include <map>
#define N 5010
#define M 10010
using namespace std;
map<int, int>mp;
struct query {int l, r, c;}q[N];
int n, y[N<<1], m;
struct seg {int l, r, lazy, mx, ls, rs;}t[M<<2];
inline void update(int p) {
if(t[p].l == t[p].r) return ;
if(t[p<<1].lazy == t[p<<1|1].lazy) t[p].lazy = t[p<<1].lazy;
t[p].mx = max(t[p<<1].mx, max(t[p<<1|1].mx, t[p<<1].rs + t[p<<1|1].ls));
t[p].ls = (t[p<<1].lazy == 1)?(t[p<<1].ls + t[p<<1|1].ls):t[p<<1].ls;
t[p].rs = (t[p<<1|1].lazy == 1)?(t[p<<1].rs + t[p<<1|1].rs):t[p<<1|1].rs;
}
inline void pushdown(int p) {
if(t[p].l == t[p].r) return ;
if(t[p].lazy) {
t[p<<1].lazy = t[p<<1|1].lazy = t[p].lazy;
if(t[p].lazy == 1) {
t[p<<1].ls = t[p<<1].mx = t[p<<1].rs = y[t[p<<1].r + 1] - y[t[p<<1].l];
t[p<<1|1].ls = t[p<<1|1].mx = t[p<<1|1].rs = y[t[p<<1|1].r + 1] - y[t[p<<1|1].l];
}else {
t[p<<1].ls = t[p<<1].mx = t[p<<1].rs = 0;
t[p<<1|1].ls = t[p<<1|1].mx = t[p<<1|1].rs = 0;
}
t[p].lazy = 0;
}
}
void build(int p, int l, int r) {
t[p].l = l; t[p].r = r;
t[p].lazy = 1; t[p].mx = t[p].ls = t[p].rs = y[r + 1] - y[l];
if(l == r) return ;
int mid = (l + r)>>1;
build(p<<1, l, mid); build(p<<1|1, mid + 1, r);
}
void ins(int p, int l, int r, int color) {
if(l > r) return ;
if(l <= t[p].l && t[p].r <= r) {
t[p].lazy = color;
if(color == 1) {t[p].mx = t[p].ls = t[p].rs = y[t[p].r + 1] - y[t[p].l];}
else {t[p].mx = t[p].ls = t[p].rs = 0;}
return ;
}
int mid = (t[p].l + t[p].r)>>1;
pushdown(p);
if(l <= mid) ins(p<<1, l, r, color);
if(mid +1 <= r) ins(p<<1|1, l, r, color);
update(p);
}
int final[M], cor[M], Q[M];
void dfs(int p) {
if(t[p].l == t[p].r) {
final[t[p].l] = (t[p].lazy == 1)?(y[t[p].l + 1] - y[t[p].l]):0;
cor[t[p].l] = (t[p].lazy == 1)?1:0;
return ;
}
pushdown(p);
dfs(p<<1); dfs(p<<1|1);
}
int main() {
scanf("%d", &n); char opt[5];
for(int i = 1; i <= n; ++i) {
scanf("%d%d%s", &q[i].l, &q[i].r, opt);
if(opt[0] == 'w') q[i].c = 1; else q[i].c = 2;
y[(i<<1) - 1] = q[i].l; y[i<<1] = q[i].r;
}
y[n<<1|1] = 0; y[(n<<1|1) + 1] = 1000000000;
sort(y+1, y+2*n+3);
m = unique(y+1, y+(n<<1|1)+2) - y - 1;
for(int i = 1; i <= m; ++i) mp[y[i]] = i;
for(int i = 1; i <= n; ++i) {q[i].l = mp[q[i].l]; q[i].r = mp[q[i].r];}
build(1, 1, m - 1);
for(int i = 1; i <= n; ++i) ins(1, q[i].l, q[i].r - 1, q[i].c);
dfs(1);
for(int i = 2; i <= m - 1; ++i) final[i]+= final[i - 1];
int cont = 0;
for(int i = 1; i <= m - 1; ++i) if(!cor[i]) Q[++cont] = i;
Q[0] = 0; Q[++cont] = m;
for(int i = 1; i <= cont; ++i) {
int last = Q[i - 1] + 1, now = Q[i] - 1;
if(last > now) continue;
if(final[now] - final[last - 1] == t[1].mx) {
printf("%d %d", y[last], y[now + 1]);
break;
}
}
return 0;
}
本文介绍了一种使用离散化线段树解决区间染色问题的经典算法。通过实例详细解析了如何处理区间更新操作,并实现了高效的区间最大值查询。文章强调了正确处理区间边界的重要性,并提供了一个完整的代码实现。

309

被折叠的 条评论
为什么被折叠?



