poj 2528 Mayor's posters(之前写的有BUG,CSDN博客那篇文章不能修改,现删掉重发)

之前写的离散化有点问题,没有考虑边界情况,比如下面这组数据。

3

1 10
1 3 

6 10

改掉离散化这个BUG有一种方法,挺麻烦的,就是如果相邻的两个数字间距大于1,就在这两个数字加点,保证不出现BUG。

我之前的代码改了改,也去掉了这个弊端。刚跟聪哥讨论了下,我越发觉得,恩,我那种做法是正确的。嘿嘿。

我的做法就是把点转化成线段,就是线段树的最后一层都是长度为1的线段,把输入的每个y点都+1,比如输入1,3,建树就建 1 4。1 4 可以看做是线段长度为3的的两个端点。这样做的话就可以完全避免上面的那种情况。最后统计段的颜色即可。

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>
#define L(x) ( x<<1 )
#define R(x) ( x<<1|1 )

using namespace std;

const int MAX = 20010;

struct Tnode{ int col,l,r;};
struct NODE{int x,y;};
NODE p[MAX/2];
Tnode node[MAX*4];
bool col[MAX/2];
int x[MAX];
void init()
{
	memset(col,0,sizeof(col));
	memset(node,0,sizeof(node));
}
void Build(int t,int l,int r)
{
	node[t].l = l;
	node[t].r = r;
	node[t].col = -1;
	if( l == r - 1 ) return ;
	int mid = ( l + r ) >> 1;
	Build(L(t), l, mid);
	Build(R(t), mid, r);
}

void Updata(int t,int l,int r,int col)
{
	if( l <= node[t].l && node[t].r <= r )
	{
		node[t].col = col;
		return ;
	}
	if( node[t].col > 0 )
	{
		node[R(t)].col = node[L(t)].col = node[t].col;
		node[t].col = -1;
	}
	int mid = (node[t].r + node[t].l) >> 1;
	if( l >= mid )
		Updata(R(t),l,r,col);
	else
		if( r <= mid )
			Updata(L(t),l,r,col);
		else
		{
			Updata(L(t),l,mid,col);
			Updata(R(t),mid,r,col);
		}
}
void Compute(int t,int l,int r)
{
	if( node[t].col > 0 )
	{
		col[node[t].col] = true;
		return ;
	}
	if( l == r - 1 ) return ;
	int mid = (node[t].r + node[t].l) >> 1;
	if( l >= mid )
		Compute(R(t),l,r);
	else
		if( r <= mid )
			Compute(L(t),l,r);
		else
		{
			Compute(L(t),l,mid);
			Compute(R(t),mid,r);
		}
}
void TT(int t)
{
	if( node[t].l == node[t].r )
		return ;
	cout << node[t].l << ' ' << node[t].r << ' ' << node[t].col << endl;
		TT(L(t));
	TT(R(t));
}
void solve(int *x,int cnt,int n)
{
	init();	
	Build(1,0,cnt+1);
	for(int i=0; i<n; i++)
	{
		int xx = lower_bound(x,x+cnt,p[i].x) - x;
		int yy = lower_bound(x,x+cnt,p[i].y) - x;
		Updata(1,xx,yy,i+1);
	//	TT(1); system("pause");
	}
	Compute(1,0,cnt+1);
	int ans = 0;
	for(int i=1; i<=n; i++)
		if( col[i] ) ans++;
	printf("%d\n",ans);
}
int main()
{
	int ncases,n;
	
	scanf("%d",&ncases);
	
	while( ncases-- )
	{
		scanf("%d",&n);
		int cnt = 0;
		for(int i=0; i<n; i++)
		{
			scanf("%d%d",&p[i].x,&p[i].y);
			p[i].y++;
			x[cnt++] = p[i].x;
			x[cnt++] = p[i].y;
		}
		sort(x,x+cnt);
		cnt = unique(x,x+cnt) - x;
		solve(x,cnt,n);
	}
return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值