zoj 2301 || hdu 1199 Color the Ball 线段树 离散化

来源:互联网 发布:汤姆克兰西知乎 编辑:程序博客网 时间:2024/06/06 06:39

题目链接:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1301

题意:

[l,r],染成w/b, 初始全为b,问最长段的w

题解:

因为N小于2000,染色范围可以到2^31,所以要离散化

http://blog.csdn.net/zxy_snow/article/details/6639878
其实这题的意思是 染色区间【闭区间】,而不是点,但是我们把r往右移一个格就转化为点了。
这里写图片描述
给一组数据,应该输出1 5
2
1 3 w
4 5 w
更新的是点,使右边加一,就变成连续的区间了。否则就更新不上去1~5这整块区间了
这里写图片描述

代码:

#include <bits/stdc++.h>using namespace std;typedef long long ll;#define MS(a) memset(a,0,sizeof(a))#define MP make_pair#define PB push_backconst int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;inline ll read(){    ll x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}//////////////////////////////////////////////////////////////////////////const int maxn = 4010+10;int x[maxn],y[maxn],c[maxn],tmp[2*maxn],vis[maxn];int cnt;char ch;struct node{    int l,r,col;}t[maxn<<2];void build(int rt,int l,int r){    if(l >= r) return ;    t[rt].l=l,t[rt].r=r,t[rt].col=0;    if(l == r-1) return ;    int mid = (l+r)/2;    build(rt<<1,l,mid);    build(rt<<1|1,mid,r);}void update(int rt,int l,int r,int c){    if(l >= r) return ;    int L=t[rt].l,R=t[rt].r;    if(l<=L && R<=r){        // cout << rt << " " << l << " " << r << " " << L << " " << R << " uuu\n";        t[rt].col = c;        return ;    }    if(t[rt].col>=0 && t[rt].col!=c){        t[rt<<1].col=t[rt<<1|1].col = t[rt].col;        t[rt].col = -1;    }    int mid = (L+R)/2;    if( l >= mid )          update(rt<<1|1,l,r,c);    else          if( r <= mid )              update(rt<<1,l,r,c);         else          {              update(rt<<1,l,mid,c);            update(rt<<1|1,mid,r,c);        }  }void query(int rt){    int L=t[rt].l,R=t[rt].r;    if(t[rt].col >= 0){        // cout << rt << " " << L << " " << R << endl;        for(int i=L; i<R; i++)            vis[i] = t[rt].col;        return ;    }    if(L == R) return ;    query(rt<<1);    query(rt<<1|1);}int main(){    int n;    while(cin>>n){        cnt = 0;        MS(x);MS(y);MS(c);MS(tmp);        for(int i=0; i<n; i++){            scanf("%d%d %c",&x[i],&y[i],&ch);            y[i]++; // 2                    // 1 3 w                    // 4 5 w  更新的是点,使右边加一,就变成连续的区间了。否则就更新不上去1~5这整块区间了            tmp[cnt++] = x[i];            tmp[cnt++] = y[i];            if(ch == 'w') c[i] = 1;        }        sort(tmp,tmp+cnt);        cnt = unique(tmp,tmp+cnt)-tmp;        build(1,0,cnt);        for(int i=0; i<n; i++){            int p1,p2;            p1 = lower_bound(tmp,tmp+cnt,x[i])-tmp;            p2 = lower_bound(tmp,tmp+cnt,y[i])-tmp;            update(1,p1,p2,c[i]);        }        memset(vis,0,sizeof(vis));        query(1);        // cout << t[1].col << "  ppp\n";        // for(int i=0; i<cnt; i++)        //  cout << tmp[i] << " ";        // cout << endl;        tmp[cnt] = tmp[cnt-1];        int s=0,e=0,ts,te;        for(int i=0; i<cnt; i++){              if( vis[i] != 1 ) continue;              ts = tmp[i];              while( vis[i] == 1 )  // 查询使得[L,R)的vis变为1, 在R的位置也是符合的,但是不赋值为1,所以跳出循环时候的i也是符合的                i++;              if( i > cnt ) break;              te = tmp[i];              if( te - ts > e - s ) {                  e = te;                  s = ts;              }          }      if( s == e )          printf("Oh, my god\n");      else          printf("%d %d\n",s,e-1);      }    return 0;}
0 0