您的位置:首页 > 其它

【HDU1199】 离散化线段树

2013-04-27 23:27 411 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1199

题目大意: 一段长度未知的线段,一种操作:a b c ,表示区间[a,b]要涂的颜色,c=w涂白色,c=b涂黑色,问你最长的白色区间段时多长。

解题思路:

就快去南京邀请赛了,最近做题超没状态,CF rating一直掉,这么简单的线段树离散化居然搞了我一个晚上,纠结。

开始用线段树区间合并的方法做,WA到死,换个写法,又WA到死,没处理好边界问题。

这题用普通的离散化没用,藐视这种离散化第一次遇见,以前的离散化要么就是点化点,线段化点,这题不一样,是点化线段,一不小心处理不好就WA了。

点化线段我利用的是左闭右开,即对于一段区间[a,b],转化成区间[a,b+1),接下来就是把所有端点当做简单的离散化处理了,然后运用线段树成段更新操作处理就好了。

View Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define lz 2*u,l,mid
#define rz 2*u+1,mid,r   ///注意:这里是点化为线段(左闭右开)
const int maxn=5555;
const int oo=0x3fffffff;
int flag[4*maxn], color[maxn];
int X[maxn];

struct Node
{
int lx, rx, s;
Node(){}
Node(int lx_, int rx_, int s_)
{
lx=lx_, rx=rx_, s=s_;
}
}line[maxn];

void push_down(int u, int l, int r)
{
if(flag[u]==-1) return ;
else
{
flag[2*u]=flag[2*u+1]=flag[u];
flag[u]=-1;
}
}

void Update(int u, int l, int r, int tl, int tr, int c)
{
if(tl>=tr) return ; ///这里要注意了
if(tl<=l&&r<=tr)
{
flag[u]=c;
return ;
}
push_down(u,l,r);
int mid=(l+r)>>1;
if(tr<=mid) Update(lz,tl,tr,c);
else if(tl>mid) Update(rz,tl,tr,c);
else
{
Update(lz,tl,mid,c);
Update(rz,mid,tr,c);
}
}

void Query(int u, int l, int r)
{
if(l>=r) return ; ///!!!
if(flag[u]!=-1)
{
for(int i=l; i<r; i++) color[i]=flag[u];  ///右端点不标记
return ;
}
push_down(u,l,r);
int mid=(l+r)>>1;
Query(lz);
Query(rz);
}

int find(int tmp, int n)
{
int l=1, r=n, mid;
while(l<=r)
{
mid=(l+r)>>1;
if(X[mid]==tmp) return mid;
else if(X[mid]<tmp) l=mid+1;
else r=mid-1;
}
}

int main()
{
int n, x, y, c;
char ch[3];
while(~scanf("%d",&n))
{
int num=0;
for(int i=0; i<n; i++)
{
scanf("%d%d%s",&x,&y,ch);
if(*ch=='w') c=1;
else c=0;
line[i]=Node(x,y+1,c);
X[++num]=x;
X[++num]=y+1;
}
sort(X+1,X+num+1);
int ep=1;
for(int i=2; i<=num; i++)
if(X[ep]!=X[i]) X[++ep]=X[i];
memset(color,0,sizeof(color));
memset(flag,-1,sizeof(flag));
for(int i=0; i<n; i++)
{
int lx=find(line[i].lx,ep);
int rx=find(line[i].rx,ep);
Update(1,1,ep+1,lx,rx,line[i].s);
}
Query(1,1,ep+1);
int s=0, d=0, ts, td;
for(int i=1; i<=ep; i++)
{
if(color[i]!=1) continue;
ts=X[i];
while(color[i]==1) i++;
if(i>ep) break;
td=X[i];
if(td-ts>d-s)
{
s=ts;
d=td;
}
}
if(s==d) puts("Oh, my god");
else printf("%d %d\n",s, d-1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: