hihoCoder - 1079 - 离散化 (线段树 + 离散化)

#1079 : 离散化

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~

这天小Hi和小Ho所在的学校举办社团文化节,各大社团都在宣传栏上贴起了海报,但是贴来贴去,有些海报就会被其他社团的海报所遮挡住。看到这个场景,小Hi便产生了这样的一个疑问——最后到底能有几张海报还能被看见呢?

于是小Ho肩负起了解决这个问题的责任:因为宣传栏和海报的高度都是一样的,所以宣传栏可以被视作长度为L的一段区间,且有N张海报按照顺序依次贴在了宣传栏上,其中第i张海报贴住的范围可以用一段区间[a_i, b_i]表示,其中a_i, b_i均为属于[0, L]的整数,而一张海报能被看到当且仅当存在长度大于0的一部分没有被后来贴的海报所遮挡住。那么问题就来了:究竟有几张海报能被看到呢?

提示一:正确的认识信息量

提示二:小Hi大讲堂之线段树的节点意义

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第1行为两个整数N和L,分别表示总共贴上的海报数量和宣传栏的宽度。

每组测试数据的第2-N+1行,按照贴上去的先后顺序,每行描述一张海报,其中第i+1行为两个整数a_i, b_i,表示第i张海报所贴的区间为[a_i, b_i]。

对于100%的数据,满足N<=10^5,L<=10^9,0<=a_i<b_i<=L。

输出

对于每组测试数据,输出一个整数Ans,表示总共有多少张海报能被看到。

样例输入
5 10
4 10
0 2
1 6
5 9
3 4
样例输出
5

待理解。。。

AC代码:

#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 200005;

struct Poster {
	int l, r;
}pt[maxn];

struct Tree {
	int l ,r;
	int c;
	int mid() { return (l + r) >> 1; }
}node[maxn << 2];

int d[maxn];
int c;

int used[maxn];

void build(int l, int r, int rt) {
	node[rt].l = l;
	node[rt].r = r;
	node[rt].c = 0;
	if(l + 1 == r) {
		return;
	}
	int mid = node[rt].mid();
	build(l, mid, rt << 1);
	build(mid, r, rt << 1 | 1);
}

void update(int l, int r, int c, int rt) {
	if(l <= node[rt].l && node[rt].r <= r) {
		node[rt].c = c;
		return;
	}
	int mid = node[rt].mid();
	if(node[rt].c != -1) {	//有新的海报贴进来,所以说要将当前这一块往下更新
		node[rt << 1].c = node[rt << 1 | 1].c = node[rt].c;
		node[rt].c = -1;
	}

	//对于当前区间的三种情况
	if (r <= mid) update(l, r, c, rt << 1);
	else if (l >= mid) update(l, r, c, rt << 1 | 1);
	else
	{
		update(l, mid, c, rt << 1);
		update(mid, r, c, rt << 1 | 1);
	}
}

void query(int rt)
{
	if (node[rt].c != -1)
	{
		used[node[rt].c] = 1;
		return;
	}
	query(rt << 1);
	query(rt << 1 | 1);
}

int main() {
	int n, l;
	scanf("%d %d", &n, &l);

	if(n == 0) {
		printf("0\n");
		return 0;
	}

	c = 0;
	for(int i = 1; i <= n; i ++) {
		scanf("%d %d", &pt[i].l, &pt[i].r);
		d[c ++] = pt[i].l;
		d[c ++] = pt[i].r;
		used[i] = 0;
	}

	sort(d, d + c);

	c = unique(d, d + c) - d; //去重 

//	for(int i = 0; i < c; i ++) {
//		cout << d[i] << " ";
//	}
//	cout << endl;

	build(0, 2 * c + 1, 1);

	for(int i = 1; i <= n; i ++) { //模拟离散化贴海报的过程,从1到n张海报
		int x = lower_bound(d, d + c, pt[i].l) - d;
		int y = lower_bound(d, d + c, pt[i].r) - d;
//		cout << x << " " << y << " " << (x << 1) << " " << (y << 1 | 1)  << endl;
		update(x << 1, y << 1 | 1, i, 1);
	}

	query(1);
	int ans = 0;
	for (int i = 1; i <= n; i ++) ans += used[i];
	printf("%d\n", ans);

	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 03:00:37

hihoCoder - 1079 - 离散化 (线段树 + 离散化)的相关文章

hihoCoder:#1079(线段树+离散化)

题目大意:给n个区间,有的区间可能覆盖掉其他区间,问没有完全被其他区间覆盖的区间有几个?区间依次给出,如果有两个区间完全一样,则视为后面的覆盖前面的. 题目分析:区间可能很长,所以要将其离散化.但离散化之后区间就变成了连续的,不再是离散的.也就是叶子由左右端点为u.u变成了左右端点为u-1.u,左右儿子有(l,mid)和(mid+1,r)变成了(l,mid)和(mid,r).所以离散化之后要以长度为1的区间为叶子节点建立线段树,而不是以1.2.3...为叶子节点建线段树. 代码如下: # inc

POJ_2528 Mayor&#39;s poster(线段树+离散化)

题目请点我 题解: 这道题与之前的题目相比重点在于一个映射的预处理,题目所给的区间达到10000000,而最多只有10000个点,如果直接建树的话太过于空旷.把这些区间的左右节点一一对应,最多有4×10000个点,远小于之前的10000000,而且区间之间的对应关系也不会改变. 举个例子: 区间:[2,6],[4,8],[6,10] 我们进行下面对应: 2 4 6 8 10 1 2 3 4 5 则原区间变为[1,3],[2,4],[3,5].可以发现它们之间的覆盖关系并没有改变,但是却紧凑了很多

POJ - 2528 - Mayor&#39;s posters 【线段树+离散化+补点】

http://poj.org/problem?id=2528 #include <cstdio> #include <iostream> #include <set> #include <cstring> #include <string> #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = 32768 + 5; in

HDU5124:lines(线段树+离散化)或(离散化思想)

http://acm.hdu.edu.cn/showproblem.php?pid=5124 Problem Description John has several lines. The lines are covered on the X axis. Let A is a point which is covered by the most lines. John wants to know how many lines cover A. Input The first line conta

hdu1828 Picture(线段树+离散化+扫描线)两种方法

C - Picture Time Limit:2000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or

poj 2528 Mayor&#39;s posters【离散化+线段树】

题目:poj 2528 Mayor's posters 题意:给一个长度非常长的墙上贴长度为ai的海报,由于有的会覆盖掉,求最后能看见的海报个数. 分析:题目和POJ2777 一模一样,方法也一样,只不过这个要离散化,其次要数组开大一点.至少2倍. 离散化的时候用了C++的 pair 类,还是比较好用的. 代码: #include <iostream> #include <algorithm> #include <utility> #include <cstrin

POJ 2299 离散化线段树

点击打开链接 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 40827   Accepted: 14752 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by

南阳理工 题目9:posters(离散化+线段树)

posters 时间限制:1000 ms  |  内存限制:65535 KB 难度:6 描述 The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally deci

Mayor&#39;s posters(离散化线段树)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 54067   Accepted: 15713 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

Poj 2528 Mayor&#39;s posters (线段树+离散化)

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,