POJ 2528

线段树和离散化搜索,并且还需要配合记忆化搜索按照逆序判断海报是否可以被看到(倒着看,问题等价于,在新的顺序下,之后的海报不可以占据之前的海报所占据的位置)

这是道好题,可惜的是自己心不在焉最后只能借助别人题解的思路解决,中间debug了好几次。If you really want

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
using namespace std;

const int maxn= 10005;
const int maxl= 1e7+5;
const int INF= 0x3f3f3f3f;

struct Post
{
	int l, r;
}a[maxn];
struct Node
{
	int l, r;
	bool ocp;
}segTree[maxn<<3];
int cor[maxn<<1], hsh[maxl];

void Build(int i, int l, int r)
{
	if (l> r){
		return;
	}
	segTree[i].l= l;
	segTree[i].r= r;
	segTree[i].ocp= false;
	if (l< r){
		int mid= (l+r)>>1;
		Build(i<<1, l, mid);
		Build((i<<1)|1, mid+1, r);
	}
}
bool Query(int i, int l, int r)
{
	if (l> r || segTree[i].ocp){
		return false;
	}
	if (l== segTree[i].l && r== segTree[i].r){
		segTree[i].ocp= true;
		return true;
	}
	int mid= (segTree[i].l+segTree[i].r)>>1;
	bool ret= false;
	if (mid< l){
		ret= Query((i<<1)|1, l, r);
	}
	else if (mid>= r){
		ret= Query(i<<1, l, r);
	}
	else{
		bool b1= Query(i<<1, l, mid);
		bool b2= Query((i<<1)|1, mid+1, r);
		ret= b1|b2;
	}

	if (segTree[i<<1].ocp && segTree[(i<<1)|1].ocp){
		segTree[i].ocp= true;
	}

	return ret;
}

int main(int argc, char const *argv[])
{
	int kase;
	int n;
	scanf("%d", &kase);
	while (kase--){
		scanf("%d", &n);
		int n_cnt= 0;
		for (int i= 1; i<= n; ++i){
			scanf("%d %d", &a[i].l, &a[i].r);
			cor[n_cnt++]= a[i].l;
			cor[n_cnt++]= a[i].r;
		}
		sort(cor, cor+n_cnt);
		n_cnt= unique(cor, cor+n_cnt)-cor;
		for (int i= 0; i< n_cnt; ++i){
			hsh[cor[i]]= i;
		}
		Build(1, 0, n_cnt-1);
		int ans= 0;
		for (int i= n; i> 0; --i){
			if (Query(1, hsh[a[i].l], hsh[a[i].r])){
				++ans;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}
posted @ 2021-05-19 20:46  IdiotNe  阅读(30)  评论(0编辑  收藏  举报