您的位置:首页 > 其它

POJ 2528 Mayor's posters(离散化+线段树)

2010-07-17 23:09 495 查看
//线段树的染色类型题目
//这题通过逆序修改线段树可以简单的实现,这是一种比较巧妙地做法
//也可以通过记录左颜色和右颜色来维护线段树实现
//下面的代码是通过逆序覆盖来实现的,逆序覆盖,即将最后一次贴上去的海报优先处理
//这样的话可以省去很多按顺序插入处理步骤,但是无法实现动态询问
//在离散化的时候我一开始使用MAP来实现,结果800MS,差点爆掉,实践证明MAP的查询速度是很慢的,还不如写个二分搞定
//但下面的代码严格来说是错误的,离散化有问题,不过数据太弱,还是可以AC的
#include<iostream>
#include<algorithm>
#include<vector>
#define MAX 10005
using namespace std;
struct seg
{
int l,r,color,cover;
}segTree[8 * MAX];//4 是线段树特征,2是10000次边最坏有20000个不同边界,所以要*8
struct Extent//区间的结构体
{
int x,y;
}extent[MAX];
bool vis[2 * MAX];
int M[2 * MAX];
int ans,N;
void buildTree(int fa,int l,int r)//建树
{
segTree[fa].l = l;
segTree[fa].r = r;
segTree[fa].color = segTree[fa].cover = 0;
if(l == r)	return;
int mid = (segTree[fa].l + segTree[fa].r) >> 1;
if(r <= mid)	buildTree(2*fa,l,r);
else if(l > mid)	buildTree(2*fa+1,l,r);
else
{
buildTree(2*fa,l,mid);
buildTree(2*fa+1,mid+1,r);
}
}
int getIndex(int data)//通过二分查找返回离散后的数组下标
{
int mid,x = 1,y = N+1;
while(x < y)
{
mid = x + (y - x) / 2;//确保分界点总是靠近区间起点
if(M[mid] == data)	return mid;
else if(M[mid] >  data)	y = mid;
else x = mid + 1;
}
return -1;
}
void insert(int fa,int l,int r,int color)
{
if(segTree[fa].cover > 0)	return;//逆序覆盖,所以如果该区间已被覆盖过了,就直接返回即可,因为前面的覆盖对结果没有影响
if(l == segTree[fa].l && r == segTree[fa].r)
{
if(segTree[fa].cover == 0)
{
segTree[fa].color = color;//染色
segTree[fa].cover = 1;
if(!vis[color])//如果这种颜色没出现过
{
++ans;
vis[color] = 1;
}
}
return;
}
int mid = (segTree[fa].l + segTree[fa].r) >> 1;
if(r <= mid)	insert(2*fa,l,r,color);
else if(l > mid)	insert(2*fa+1,l,r,color);
else
{
insert(2*fa,l,mid,color);
insert(2*fa+1,mid+1,r,color);
}
if(segTree[2*fa].cover > 0 && segTree[2*fa+1].cover > 0)//通过回溯跟结点顺便维护区间的覆盖情况
segTree[fa].cover = 1;
}
int main()
{
//freopen("in.txt","r",stdin);
int t,n,x,y;
scanf("%d",&t);
while(t--)
{
N = 0;
int color = 0;
scanf("%d",&n);
vector<int> v;
memset(vis,0,sizeof(vis));
ans = 0;
for(int i = 0;i < n;++i)
{
scanf("%d%d",&extent[i].x,&extent[i].y);
v.push_back(extent[i].x);
v.push_back(extent[i].y);
}
sort(v.begin(),v.end());
//离散化过程
M[++N] = v[0];
for(int i = 1;i < v.size();++i)
if(v[i] != v[i-1])
M[++N] = v[i];
buildTree(1,1,N);
for(int i = n - 1;i >= 0;--i)
{
x = getIndex(extent[i].x);
y = getIndex(extent[i].y);
insert(1,x,y,++color);//对每条边插入不同的颜色
}
printf("%d/n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: