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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章