HDU 1199 Color the Ball(離散化入門+非線段樹做法)

HDU 1199 Color the Ball

題意

  1. 一個數軸,數軸上點的座標從1~1e9
  2. 一共有n次操作,以a,b,c形式輸入,是把a~b的這段區間染色成白色/黑色
  3. 詢問n次操作後,最長的連續白色區間,輸出區間的左端點和右端點

解決

  1. 注意到點的範圍很大,而且只有2000個區間,4000個點,點十分稀疏,不能使用普通數組進行存儲
  2. 初學離散化,這是我做的第一道離散化的題(新手入門,還望見諒)
  3. 剛開始是想離散化後只有4000個點,直接暴力模擬一遍,樣例過了但是被wa了
  4. 後來和隊友交流的時候,發現對於14 16 w 、 19 20 w這樣的操作,我的程序在便利的時候會把17~18的這一段也當成白色的,進而得到14~20這樣的錯誤區間,還有一個問題就是對於1 4 w、3 5 b這樣的操作,我的程序並不能得到1~2均爲白色,而是把1當做單一的白色節點來處理。
  5. 解決上述錯誤:我在離散化的時候,把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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章