ural1019 找最长全白线段

【题目描述】

        先是在数轴区间 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 Input
4
1 999999997 b
40 300 w
300 634 w

43 47 b


Sample Output

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;
}

猜你喜欢

转载自blog.csdn.net/richard_for_oi/article/details/79735366