URAL1019. Line Painting

针对在[0,1E9]区间内进行多次黑白涂色操作的问题,通过离散化和线段树等数据结构,设计算法寻找最终形成的最长连续白色区间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The segment of numerical axis from 0 to 109 is painted into white color. After that some parts of this segment are painted into black, then some into white again and so on. In total there have been made N re-paintings (1 ≤ N ≤ 5000). You are to write a program that finds the longest white open interval after this sequence of re-paintings.

Input

The first line of input contains the only number N. Next N lines contain information about re-paintings. Each of these lines has a form:
ai bi ci
where ai and bi are integers, ci is symbol 'b' or 'w', aibici are separated by spaces. 
This triple of parameters represents repainting of segment from ai to bi into color ci ('w' — white, 'b' — black). You may assume that 0 < ai < bi < 109.

Output

Output should contain two numbers x and y (x < y) divided by space(s). These numbers should define the longest white open interval. If there are more than one such an interval output should contain the one with the smallest x.

Sample

input output
4
1 999999997 b
40 300 w
300 634 w
43 47 b
47 634

涂色问题:

将[0,1E9]区间涂色,只能涂白色和黑色,可覆盖,求最长的白色区间。

思路:

离散化,可以将点的数量下降到2*N  接下来看可以用线段树(NlogN)或者暴力(N*N)查找答案,这题是被自己坑了,在test2弹了好几次。

只要注意这组样例:

1

10 11 b

answer is 11 1000000000

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
struct paint{
	int  l,r;
	char op;
};
int len;
vector<bool>vis;
vector<paint> vp,tp;
vector<int> tn;
map<int,int> yp,kp;
void init(){
	
}
void disret(){
	vis.resize(tn.size());
	for(int i = 0; i < vis.size(); i++)
		vis[i] = 0;
	sort(tn.begin(),tn.end());
	int k = 0;
	for(int i = 0; i < tn.size(); i++){
		while(tn[i]==tn[i+1]&&i<tn.size()-1){
			i++;
		}
		kp[k] = tn[i];
		yp[tn[i]] = k++;
	}
	//for(int i = 0; i < k; i++){
		//cout<<kp[i]<<endl;
	//}
	for(int i = 0; i < vp.size(); i++){
		int l = yp[vp[i].l];
		int r = yp[vp[i].r];
		//cout<<l<<" "<<r<<endl;
		for(int j = l; j <= r-1; j++){
			if(vp[i].op=='b'){
				vis[j] = 1;
			}else{
				vis[j] = 0;
			}
		}
	}
	//for(int i =0 ;i < k-1; i++)
		//cout<<vis[i]<<endl;
	len = k; 
}
void solve(){
	disret();
	int ans = 0,l=0,r=0;
	for(int i = 0; i < len-1; i++){
		if(vis[i]==0){
			int j = i;
			while(vis[j]==0&&j<len-1)
				j++;
			if(ans < kp[j]-kp[i]){
				l = kp[i];
				r = kp[j];
				ans = kp[j]-kp[i];
			}
			i = j;	
		}
	}
	cout<<l<<" "<<r<<endl;
}
int main(){
	int n;
	scanf("%d",&n);
	tn.push_back(0);
	tn.push_back(1000000000);
	while(n--){
		paint tmp;
		cin >> tmp.l >> tmp.r >> tmp.op;
		tn.push_back(tmp.r);
		tn.push_back(tmp.l);
		vp.push_back(tmp);	
	}
	solve();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值