hdu 1199 Color the Ball (线段树区间合并,离散化)

来源:互联网 发布:java中的重载 编辑:程序博客网 时间:2024/06/04 18:22

题目大意:

有若干个球以及n次操作,每次操作把区间 [ a , b ] 的球涂成一种颜色,w 表示涂成白色,b 表示涂成黑色。初始的时候所有的球都是黑色的。

问:n次操作以后,最长的连续白色的区间,如果有多个,输出最左边的那个。

解题思路:

这是一道很明显的线段树区间合并的题目。开了一个结构体,其中 lenl 表示从左往右连续的白色球的数量,lenr 表示从右往左连续的白色球的数量,len表示在当前区间情况下,最长的连续的白色球的数量。我们可以看到:一个区间的 连续最长的白色球的数量 可能全部来自 他的左区间,也可能全部来自他的右区间,另外还可能是横跨了两个子区间,所以,我们这边需要记录lenl 以及lenr 的值 。

这道题跟一般的线段树区间合并的题目不同的是,这道题需要离散化处理。因为a b 的范围不知,所以需要进行离散化。另外,在进行离散化的时候,我们需要额外增加一些点,防止出现比如  1 4 w  8 10 w 输出 1 10这种忽略了 中间5 7 为b 的情况。所以我们需要额外增加点。为了操作简单,我在读入的时候分别在前面,后面加入一个点 a [ i ] - 1, a [ i ] + 1;  然后再进行离散化以及后续的线段树操作。

线段树一个区间的长度表示的是该点最右端的离散化前的值到他前一个区间的最右端离散化后的值。即 对于 区间为 [ l , r ] 的线段树长度为 x [ r ] - x [ l ] ;

具体看代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define maxn 120000struct node{    int lenl,lenr,len,col;} sum[maxn];int x[12000];//离散化void setlen(int rt,int num){    sum[rt].len=sum[rt].lenl=sum[rt].lenr=num;}void pushup(int rt,int l,int r){    sum[rt].lenl=sum[rt<<1].lenl;    sum[rt].lenr=sum[rt<<1|1].lenr;    sum[rt].len=max(max(sum[rt<<1].len,sum[rt<<1|1].len),sum[rt<<1].lenr+sum[rt<<1|1].lenl);    int m=(l+r)>>1;    int temlenl=x[m]-x[l-1];    int temlenr=x[r]-x[m];    if(sum[rt<<1].lenl==temlenl)sum[rt].lenl+=sum[rt<<1|1].lenl;    if(sum[rt<<1|1].lenr==temlenr)sum[rt].lenr+=sum[rt<<1].lenr;}void pushdown(int rt,int l,int r){    if(sum[rt].col!=-1)    {        sum[rt<<1].col=sum[rt<<1|1].col=sum[rt].col;        int m=(l+r)>>1;        int temlenl=x[m]-x[l-1];        int temlenr=x[r]-x[m];        setlen(rt<<1,temlenl*sum[rt].col);        setlen(rt<<1|1,temlenr*sum[rt].col);        sum[rt].col=-1;    }}void build(int l,int r,int rt){    setlen(rt,0);    sum[rt].col=-1;    if(l==r)return ;    int m=(l+r)>>1;    build(lson);    build(rson);}void update(int l,int r,int rt,int L,int R,int c){    if(l>=L&&r<=R)    {        sum[rt].col=c;        setlen(rt,(x[r]-x[l-1])*c);        return ;    }    pushdown(rt,l,r);    int m=(l+r)>>1;    if(m>=L)update(lson,L,R,c);    if(m<R) update(rson,L,R,c);    pushup(rt,l,r);}int query(int l,int r,int rt){    if(l==r)return x[l];    int m=(l+r)>>1;    pushdown(rt,l,r);    if(sum[rt<<1].len==sum[1].len)return query(lson);    else if(sum[rt<<1].lenr+sum[rt<<1|1].lenl==sum[1].len)return x[m]-sum[rt<<1].lenr+1;    else return query(rson);}int sea(int num,int l,int r){    int mid=(l+r)>>1;    while(l<=r)    {        if(x[mid]==num)return mid;        else if(x[mid]<num)l=mid+1;        else r=mid-1;        mid=(l+r)>>1;    }}int main(){    int n,i,j,k,all;    int a[2222],b[2222];    char s[2222][3];    while(scanf("%d",&n)==1)    {        j=0;        for(i=0; i<n; i++)        {            scanf("%d%d%s",&a[i],&b[i],s[i]);            x[j++]=a[i]-1;            x[j++]=a[i];            x[j++]=a[i]+1;            x[j++]=b[i]-1;            x[j++]=b[i];            x[j++]=b[i]+1;        }        sort(x,x+j);        all=0;        for(i=1; i<j; i++)            if(x[i]!=x[i-1])x[++all]=x[i];        build(1,all,1);        for(i=0; i<n; i++)        {            int tema=sea(a[i],0,all);            int temb=sea(b[i],0,all);            if(s[i][0]=='w')update(1,all,1,tema,temb,1);            else update(1,all,1,tema,temb,0);        }        if(sum[1].len<=0)printf("Oh, my god\n");        else        {            int ansl=query(1,all,1);            int ansr=ansl+sum[1].len-1;            printf("%d %d\n",ansl,ansr);        }    }    return 0;}


0 0
原创粉丝点击