poj2528

这道题的关键就是逆向思维(雾),把海报倒过来贴,那么对于每一张海报,只要还有空地就可以返回真

另外就是离散化的过程,不可无限制的紧缩,对于不相邻的,一定要增加一个点将它们隔开,这样在覆盖时才不会有偏差

#include <iostream>
#include <cstdio>
#include <algorithm>
 
using namespace std;
const int maxn = 20000 + 5;
 
int pl[maxn], pr[maxn], n;
 
int s[maxn*4], e[maxn*4];
bool covered[maxn*4];	
 
int port[maxn], cnt;
int id[10000000+5];
 
void build_tree(int l, int r, int rt){
	s[rt] = l;
	e[rt] = r;
	covered[rt] = false;
 
	if(l != r){
		build_tree(l, (l + r) / 2, rt << 1);
		build_tree((l + r) / 2 + 1, r, rt << 1 | 1);
	}
}
 
bool post(int l, int r, int rt){
	if(covered[rt] == true)	return false;
	if(s[rt] == l && e[rt] == r){
		covered[rt] = true;
		return true;
	}
 
	bool res;
	if(r <= (s[rt] + e[rt]) / 2)	res = post(l, r, rt << 1);
	else if(l > (s[rt] + e[rt]) / 2)	res = post(l, r, rt << 1 | 1);
	else {
		bool res1 = post(l, (s[rt] + e[rt]) / 2, rt << 1);
		bool res2 = post((s[rt] + e[rt]) / 2 + 1, r, rt << 1 | 1);
		res = res1 || res2;
	}
 
	if(covered[rt << 1] && covered[rt << 1 | 1])	covered[rt] = true;
 
	return res;
}
 
int main(){
	int T;
	scanf("%d", &T);
	while(T--){
		scanf("%d", &n);
		cnt = 0;
		for(int i = 0; i < n; i++){
			scanf("%d%d", &pl[i], &pr[i]);
			port[cnt++] = pl[i];
			port[cnt++] = pr[i];
		}
 
		sort(port, port + cnt);
		cnt = unique(port, port + cnt) - port;
 
		build_tree(1, cnt, 1);
 
		for(int i = 0; i < cnt; i++)	id[port[i]] = i + 1;
 
		int res = 0;
		for(int i = n-1; i >= 0; i--){
			if(post(id[pl[i]], id[pr[i]], 1)){
				res ++;
			}
		}
		printf("%d\n", res);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/82501944