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