HDU 1199 Color the Ball
题意
- 一个数轴,数轴上点的座标从1~1e9
- 一共有n次操作,以a,b,c形式输入,是把a~b的这段区间染色成白色/黑色
- 询问n次操作后,最长的连续白色区间,输出区间的左端点和右端点
解决
- 注意到点的范围很大,而且只有2000个区间,4000个点,点十分稀疏,不能使用普通数组进行存储
- 初学离散化,这是我做的第一道离散化的题(新手入门,还望见谅)
- 刚开始是想离散化后只有4000个点,直接暴力模拟一遍,样例过了但是被wa了
- 后来和队友交流的时候,发现对于14 16 w 、 19 20 w这样的操作,我的程序在便利的时候会把17~18的这一段也当成白色的,进而得到14~20这样的错误区间,还有一个问题就是对于1 4 w、3 5 b这样的操作,我的程序并不能得到1~2均为白色,而是把1当做单一的白色节点来处理。
- 解决上述错误:我在离散化的时候,把a-1 a+1 a b-1 b+1 b都做了离散化,这样的话,就不会影响到相邻点了。
继续拿14 16 w 、 19 20 w的操作为例
在执行完这两个操作后应该是这样的情况
13 -> 无色
14 -> 白色
15 -> 白色
16 -> 白色
17 -> 无色
18 -> 无色
19 -> 白色
20 -> 白色
21 -> 无色
那么我们就能解决掉程序无法判断17~18仍为无色的问题,进而得不到14~20这个不合法的区间
同样,我们拿1 4 w、3 5 b的例子再来看一下为什么+1和-1就能解决这个问题
在执行上述操作后,应该是这个情况
0 -> 无色 0 -> 无色
1 -> 白色 1 -> 白色
2 -> 白色 3 5 b 2 -> 白色
3 -> 白色 ------>>>> 3 -> 黑色
4 -> 白色 4 -> 黑色
5 -> 无色 5 -> 黑色
6 -> 无色 6 -> 无色
如果没有理解,可以自己在草稿纸上模拟一下
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<cstdio>
using namespace std;
int a[2005] , b[2005] , c[2005];
int num[13000]; //用来保存离散化后的点的状态,0为无色,-1为黑色,1为白色
vector<int> V; //一个区间会被拆成6个点,所以开6x2000的数组
map<int,int> val2key; //真实值(val)到离散化后的值(key)的映射关系
map<int,int> key2val; //离散化后的值(key)到真实值(val)的映射关系
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(num,0,sizeof(num));
V.clear();
val2key.clear();
key2val.clear();
for(int i=0;i<n;i++){
scanf("%d %d %c",&a[i],&b[i],&c[i]);
V.push_back(a[i]);
V.push_back(a[i]-1);
V.push_back(a[i]+1);
V.push_back(b[i]);
V.push_back(b[i]-1);
V.push_back(b[i]+1);
}
//离散化操作
sort(V.begin() , V.end());
int len = unique(V.begin(),V.end())-V.begin();
for(int i=0;i<len;i++){
val2key[V[i]] = i+1;
key2val[i+1] = V[i];
}
for(int i=0;i<n;i++){
int l = val2key[a[i]];
int r = val2key[b[i]];
if(c[i]=='w'){
for(int j=l;j<=r;j++) num[j] = 1;
}
else if(c[i]=='b'){
for(int j=l;j<=r;j++) num[j] = -1;
}
}
//for(int i=1;i<=len;i++) printf("%4d%c",i,i==len?'\n':' ');
//for(int i=1;i<=len;i++) printf("%4d%c",num[i],i==len?'\n':' ');
int ans = -1;
int ans1,ans2;
for(int i=1;i<=len;i++){
int j = i;
int tmp; //真实长度
if(num[i]==-1||num[i]==0) continue;
while(num[j]==1) j++;
tmp = key2val[j-1]-key2val[i]+1;
//printf("%d len = %d\n",i,tmp);
if(tmp>ans){
ans = tmp;
ans1 = key2val[i];
ans2 = key2val[j-1];
}
i = j-1;
}
if(ans==-1) printf("Oh, my god\n");
else printf("%d %d\n",ans1,ans2);
}
}