hdu 1199 Color the ball(线段树离散化区间染色)

题目链接:点击打开链接


线段树离散化区间染色。

数据范围是int最大值,肯定要离散化,离散化时要注意加点。

举几个个例子:

1. 输入 1,2,4,5,如果离散成1,2,3,4那么本来最长区间是1到2,离散后就变成1到4了,这就要在2和4之间加点。

2. 输入 1 5 w,3 5 b,最长区间应是1到2,但是不加点的话没有点表示2,得不到1到2这个结果,需要添加点2

3. 输入  1 5 w,1 3 b,最长区间是4到5,同理需要加4这个点


综上,离散化的步骤是先对原数组排序(代码中用tmp表示),然后加上这两句:

        if(tmp[i]-tmp[i-1]>1) Hash[++k]=tmp[i]-1;
        if(tmp[i]-tmp[i-1]>2) Hash[++k]=tmp[i-1]+1;


另外统计结果的方法是遍历叶子节点,找最长区间,所以此线段树不需要pushup,只需要能把改变传到下面的pushdown即可。


代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#include <algorithm>
using namespace std;
#define MAX 30000
int Hash[MAX*2];
int res[MAX<<2];
int col[MAX<<2];
int ans[MAX*2];

struct seg{
    int s,t;
    int c;
}p[MAX];
void pushdown(int rt){
    if(col[rt]){
        col[rt<<1]=col[rt<<1|1]=col[rt];
        res[rt<<1]=res[rt<<1|1]=col[rt];
        col[rt]=0;
    }
}

void build(int l,int r,int rt){
    col[rt]=0;
    res[rt]=2;
    if(l==r) return ;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

void update(int L,int R,int c,int l,int r,int rt){
    if(L<=l&&R>=r){
        res[rt]=c;
        col[rt]=c;
        return ;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m) update(L,R,c,lson);
    if(R>m) update(L,R,c,rson);
}

void query(int l,int r,int rt){
    if(l==r){
        ans[l]=res[rt];
        return ;
    }
   
    int m=(l+r)>>1;
    query(lson);
    query(rson);
}

void solve(int n){
    long long tmp[MAX*2];
    int len=0;
    for(int i=1;i<=n;i++){
        char c[4];
        scanf("%d%d%s",&p[i].s,&p[i].t,c);

        tmp[++len]=p[i].s;
        tmp[++len]=p[i].t;

        if(c[0]=='w') p[i].c=1;
        else p[i].c=2;
    }
    sort(tmp+1,tmp+len+1);
    int k=0;
    Hash[++k]=tmp[1];
    for(int i=2;i<=len;i++){
        Hash[++k]=tmp[i];
        if(tmp[i]-tmp[i-1]>1) Hash[++k]=tmp[i]-1;
        if(tmp[i]-tmp[i-1]>2) Hash[++k]=tmp[i-1]+1;
    }
    sort(Hash+1,Hash+k+1);
    len=unique(Hash+1,Hash+k+1)-Hash-1;
    build(1,len,1);

    for(int i=1;i<=n;i++){
        int s=lower_bound(Hash+1,Hash+len+1,p[i].s)-Hash;
        int t=lower_bound(Hash+1,Hash+len+1,p[i].t)-Hash;
        if(s>t) continue;
        update(s,t,p[i].c,1,len,1);
    }
    query(1,len,1);
    int answer=-1;
    int l=0,r=0;
    bool flag=0;

    for(int i=1;i<=len;i++){
        int j=i;
        if(ans[i]==1){
          flag=1;
          int tmp=0;
          while(j<len&&ans[j+1]==1){
            j++;
          }
          tmp=Hash[j]-Hash[i];

          if(tmp>answer){
                answer=tmp;
                l=Hash[i];
                r=Hash[j];

          }

        }
        i=j;
    }
    if(!flag) printf("0\n");
    else printf("%d %d\n",l,r);

}

int main(){
    int n;
    while(~scanf("%d",&n)){
        solve(n);
    }
    return 0;
}











你可能感兴趣的:(线段树,离散化)