您的位置:首页 > 其它

POJ --2528--Mayor's posters--离散线段树

2013-03-13 21:00 417 查看
没看题目又想看题解的童鞋请先把题目看了。

题目给的区间是1到一千万,询问却只有一万个,一千万的数组是开不下的,但是询问的区间比如给了一个,1--100的区间,中间2--99都是浪费掉的了不用的区间,这个题要是能发现这点就好办 了,这也应该是这题的难点,最后采取的办法是离散化的线段树,我最先使用的离散方法是使用的STL里面的SET和MAP,但是比较遗憾的是超时了,然后看了别人博客上的题解代码,借用了别人使用数组离散化线段树的办法,成功搞定

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define mmaxn 10000004
#define maxn 10003
#define M(a) memset((a),0,sizeof(a))
#define lc(c) ((c)<<1)
#define rc(c) ((c)<<1|1)
using namespace std;
struct node
{
int l,r;
int color;
}p[maxn<<2];
struct Command
{
int l,r;
int color;
}com[maxn];

bool  reg[mmaxn],vis[maxn];
int d[maxn<<1],ic,ans;
unsigned short int tal[mmaxn];
int n;

void init()
{
M(reg);M(d);M(vis);
ans=ic=0;
int x, y;
scanf("%d",&n);		//	下面开始离散区间的一一映射处理
for(int i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
if(!reg[x])
{
d[ic++]=x;
reg[x]=1;
}
if(!reg[y])
{
d[ic++]=y;
reg[y]=1;
}
com[i].l=x;
com[i].r=y;
}
sort(d,d+ic);
for(int i=0;i<ic;i++)
tal[d[i]]=i+1;
for(int i=0;i<n;i++)
{
com[i].l=tal[com[i].l];
com[i].r=tal[com[i].r];
com[i].color=i+1;
}
//搞定了,剩下的就是常规的线段树了
}

void build(int c,int x,int y)
{
p[c].l=x;p[c].r=y;
p[c].color=0;
if(x==y)return;
int m=(x+y)>>1;
build(lc(c),x,m);
build(rc(c),m+1,y);
}
void update(int c,int x,int y,int cl)
{
int l=p[c].l,r=p[c].r;
if(x==l&&r==y)
{
p[c].color=cl;
return;
}
if(p[c].color>=0)
{
p[lc(c)].color=p[rc(c)].color=p[c].color;
p[c].color=-1;
}
int m=(l+r)>>1;
if(m>=y)update(lc(c),x,y,cl);
else if (m<x)update(rc(c),x,y,cl);
else
{
update(lc(c),x,m,cl);
update(rc(c),m+1,y,cl);
}
}
void dfs(int c)
{
int u=p[c].color;
if(u==0)return;
if(p[c].color>0)
{
if(!vis[u])
{
vis[u]=1;
ans++;
}
return;
}
dfs(lc(c));
dfs(rc(c));
}
void solve()
{
build(1,1,ic);
for(int i=0;i<n;i++)
{
update(1,com[i].l,com[i].r,com[i].color);
}
dfs(1);
printf("%d\n",ans);
}

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: