1. 程式人生 > >數算實習 Mayor's posters 線段樹 離散化

數算實習 Mayor's posters 線段樹 離散化

Mayor’s posters每個候選人都可以在牆上放置一張海報。

所有海報的高度都與牆的高度相同; 海報的寬度可以是任何整數個單位。
牆被分成10000000段,每段的寬度是一個單位。每張海報必須完全覆蓋連續數量個單位的牆壁。
你的任務是找到所有海報放置完畢後可見海報的數量。

輸入:
第一行輸入包含一個數字c,給出了後面的案例數。單個案例的第一行資料包含數字1 <= n <= 10000。隨後的n行按照海報的放置順序給出海報的左端編號和右端編號。
輸出:
海報貼上完畢後能看到的海報數量

樣例輸入
1
5
1 4
2 6
8 10
3 4
7 10

樣例輸出
4

#include <iostream>
#include <algorithm>
using namespace std;

int sum;
int flag;

struct post
{
	int l;
	int r;
};
struct cnode
{
	int l;
	int r;
	bool covered;
	cnode *left;
	cnode *right;
};
struct section
{
	int l;
	int r;
};

void buildtree(cnode* root, section* s, int le, int ri)
{
	root->covered = 0;
	if (le == ri)
		return;
	root->left = new cnode;
	root->right = new cnode;
	int mid = (le + ri) / 2;
	root->left->l = s[le].l;
	root->left->r = s[mid].r;
	root->right->l = s[mid + 1].l;
	root->right->r = s[ri].r;
	buildtree(root->left, s, le, mid);
	buildtree(root->right, s, mid + 1, ri);
}

void quary(cnode* root, int L, int R)
{
	if (root->l == L && root->r == R)
	{
		if (root->covered == 1)
			return;
		else
		{
			root->covered = 1;
			flag = 1;
			return;
		}
	}
	else
	{
		if (root->covered == 1)
			return;
		if (R <= (root->left->r))
		{
			quary(root->left, L, R);
		}
		else if (L >= (root->right->l))
		{
			quary(root->right, L, R);
		}
		else
		{
			quary(root->left, L, root->left->r);
			quary(root->right, root->right->l, R);
		}
		if (root->left->covered == 1 && root->right->covered == 1)
			root->covered = 1;
	}
}

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		post p[10002];              //記錄海報資訊
		int point[50004];           //記錄端點值
		section s[50004];           //記錄單位區間
		sum = 0;
		int n;
		cin >> n;
		int j = 0;
		for (int i = 1; i <= n; ++i)
		{
			cin >> p[i].l >> p[i].r;
			point[j++] = p[i].l;
			point[j++] = p[i].r;
		}
		sort(point, point + j);
		int len = 1;
		for (int k = 0; k < j - 1; k++)                      //離散化
		{
			if (point[k] != point[k + 1])
			{
				if (point[k + 1] - 1 == point[k])
				{
					s[len].l = point[k];
					s[len].r = point[k];
					len++;
				}
				else
				{
					s[len].l = point[k];
					s[len].r = point[k];
					len++;
					s[len].l = point[k] + 1;
					s[len].r = point[k + 1] - 1;
					len++;
				}
			}
		}
		s[len].l = point[j - 1];
		s[len].r = point[j - 1];
		cnode* root = new cnode;         
		root->l = s[1].l;
		root->r = s[len].r;
		buildtree(root, s, 1, len);
		for (int i = n; i >= 1; --i)
		{
			flag = 0;
			int L = p[i].l;
			int R = p[i].r;
			quary(root, L, R);
			sum += flag;
		}
		cout << sum << endl;
	}

	return 0;
}