poj 2528 Mayor’s posters 线段树

23 篇文章 0 订阅
14 篇文章 0 订阅
//	poj 2528 Mayor’s posters
//
//	题目大意:
//		给你n张海报,每张海报是一段区间,问最后由几张还好能露出来
//
//	解题思路:
//		线段树,别看那海报的区间范围很大,其实那些都没用.n才10000呢
//	将区间离散化之后,然后在进行线段树的操作,但是注意在相差大于1
//	的区间中间加上一个值,这样讲两个区间区分开,然后就是基本操作了
//	挺好想的

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#define For(x,a,b,c) for (int x = a; x <= b; x += c)
#define Ffor(x,a,b,c) for (int x = a; x >= b; x -= c)
#define cls(x,a) memset(x,a,sizeof(x))
using namespace std;
typedef long long ll;

const double PI = acos(-1.0);
const double EPS = 1e-10;
const int MAX_N = 80000;
const int INF = 10009;
int N,M;

int L[MAX_N],R[MAX_N];
int a[MAX_N];
int cnt;

struct IntervalTree{

#define ls(x)	(x << 1)
#define rs(x)	(x << 1 | 1)
	int col[MAX_N<<2];

	bool isc[MAX_N];

	void init(){
		cls(col,-1);
		cls(isc,0);
	}

	void push_down(int rt){
		if (col[rt]!=-1){
			col[ls(rt)] = col[rs(rt)] = col[rt];
			col[rt] = -1;
		}
	}

	void update(int rt,int L,int R,int ql,int qr,int v){
		if (ql <= L && R <= qr){
			col[rt] = v;
			return ;
		}

		push_down(rt);

		int M = (L + R) >> 1;

		if (ql <= M)	update(ls(rt),L,M,ql,qr,v);
		if (M < qr)		update(rs(rt),M+1,R,ql,qr,v);
		push_down(rt);
	}

	void query(int rt,int L,int R){
		if (col[rt] != -1){
			if (!isc[col[rt]])
				cnt++;
			isc[col[rt]] = 1;
			return ;
		}
		if(L == R) return ;
		int M = (L + R) >> 1;
		query(ls(rt),L,M);
		query(rs(rt),M+1,R);
	}


}it;



void input(){
	scanf("%d",&N);
	int tot = 1;
	for (int i = 1;i <= N;i ++){
		scanf("%d%d",&L[i],&R[i]);
		a[tot++] = L[i];
		a[tot++] = R[i];
	}

	sort(a+1,a+tot);
	int m = 2;

	for (int i = 2;i < tot ; i++){
		if (a[i] != a[i-1])
			a[m++] = a[i];
	}
	tot = m;

	for (int i = tot - 1;i >= 2;i --){
		if (a[i] - a[i-1] > 1)
			a[m++] = a[i-1] + 1;
	}

	tot = m;

	sort(a + 1, a + tot);
	
	it.init();

	for (int i = 1;i <= N;i ++){
		int l = lower_bound(a + 1,a + tot, L[i]) - a;
		int r = lower_bound(a + 1,a + tot, R[i]) - a;

		it.update(1,1,tot-1,l,r,i);
	}

	cnt = 0;
	
	it.query(1,1,tot-1);

	printf("%d\n",cnt);



}

int main(){
	int t;
	//freopen("1.in","r",stdin);
	scanf("%d",&t);
	while(t--){
		input();
	}
        return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值