hiho1079 : 离散化(线段树+区间离散化)

#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

这道题我们首先想到的就是用线段树做  可是发现数据特别大

这时候就用到离散化了。

离散化  简而言之 就是把区间缩小  但是相对大小不变  这样就能用线段树维护了

当然 还有一个注意点就是 离散的区间是[l,mid],[mid,r]  而不是[l,mid],[mid+1,r].

至于为什么这样  可以用反证法~~如果[mid,mid+1]之间有一个海报怎么存贮?

奉上代码:

#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>
using namespace std;
struct node
{
	int flag;
	int l,r;
};
vector<int>v;
int res;
int N;
bool use[100005*2+10];
node tree[40*100000];
int point_x[100005];
int point_y[100005];
int getid(int x)
{
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void build(int root,int l,int r)
{
	tree[root].flag=0;
	tree[root].l=l;
	tree[root].r=r;
	if(l+1==r) return ;
	int mid=(l+r)/2;
	build(root*2,l,mid);
	build(root*2+1,mid,r);
}
void update(int l,int r,int root,int x)
{

	if(tree[root].l==l&&tree[root].r==r)
	{
		tree[root].flag=x;
		return ;
	}
	if(tree[root].l+1>=tree[root].r) return;
	if(tree[root].flag)
	{
		tree[root*2+1].flag=tree[root*2].flag=tree[root].flag;
		tree[root].flag=0;
	}
	int mid=(tree[root].l+tree[root].r)/2;
	if(l>mid)
	update(l,r,root*2+1,x);
	else if(r<=mid)
	update(l,r,root*2,x);
	else
	{
		update(l,mid,root*2,x);
		update(mid,r,root*2+1,x);
	}
}
void query(int root)
{

	if(tree[root].flag&&!use[tree[root].flag])
	{
		res++;
		use[tree[root].flag]=true;
		return ;
	}
	if(tree[root].l+1>=tree[root].r) return ;
	if(!use[tree[root].flag])
	{
		query(root*2);
		query(root*2+1);
	}

}
int main()
{
	int n,l;
	memset(tree,0,sizeof(tree));
	v.clear();
	scanf("%d %d",&n,&l);
	for(int i=0;i<n;i++)
	{
		scanf("%d %d",&point_x[i],&point_y[i]);
		v.push_back(point_x[i]);
		v.push_back(point_y[i]);
	}
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	N=v.size();
	build(1,1,N);
	for(int i=0;i<n;i++)
	{
		update(getid(point_x[i]),getid(point_y[i]),1,i+1);
	}
	res=0;
	memset(use,false,sizeof(use));
	query(1);
	printf("%d\n",res);
	return 0;
}
时间: 2024-08-24 05:08:54

hiho1079 : 离散化(线段树+区间离散化)的相关文章

POJ 2528 Mayor&#39;s posters (离散化+线段树区间更新)

Description 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 decided to build an electoral wall for

POJ - 2528 Mayor&#39;s posters (离散化+线段树区间修改)

https://cn.vjudge.net/problem/POJ-2528 题意 给定一些海报,可能相互重叠,告诉你每个海报的宽度(高度都一样的)和先后叠放顺序,问没有被完全盖住的有多少张? 分析 海报最多10000张,但是墙有10000000块瓷砖长,海报不会落在瓷砖中间. 如果直接建树,就算不TLE,也会MLE.即单位区间长度太多. 其实10000张海报,有20000个点,最多有19999个区间.对各个区间编号,就是离散化.然后建树. 可以直接进行区间修改,最后再统计. 这里采用比较巧妙的

POJ - 2528Mayor&#39;s posters (离散化+线段树区间覆盖)

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 decided to build an electoral wall for placing the

线段树+区间离散化

校赛1007 题意 给你一个n(n<1e5),表示n个比赛直播,然后n个区间,l,r(0<=l,r<=1e9),表示比赛开始的时间和结束的时间,要同时把所有比赛看完,问最少要借多少台电脑(自己有一台电脑) 其实就是求区间重叠的最大值由于区间太大,所以离散化处理 思路:线段树区间更新 + 离散化 以区间的端点作为标记离散化,离散化后映射到线段树,将重复的端点去掉,然后重新排序,对每个区间二分确定映射后的区间,这里注意二分的时候左端点和右端点二分的判断条件是不同的 AC代码: #includ

ZOJ 2301 / HDU 1199 Color the Ball 离散化+线段树区间连续最大和

题意:给你n个球排成一行,初始都为黑色,现在给一些操作(L,R,color),给[L,R]区间内的求染上颜色color,'w'为白,'b'为黑.问最后最长的白色区间的起点和终点的位置. 解法:先离散化,为了防止离散后错误,不仅将L,R离散,还要加入L+1,L-1,R+1,R-1一起离散,这样就绝不会有问题了.然后建线段树,线段树维护四个值: 1.col  区间颜色  0 表示黑  1 表示白  -1表示无标记 2.maxi 区间内最大白区间的长度,由于白色用1表示,所以最大白区间的长度即为区间最

POJ2528(离散化+线段树区间更新)

#include"cstdio" #include"algorithm" using namespace std; const int MAXN=10005; struct Post{ int l,r; }posters[MAXN]; int x[MAXN*2]; int hash[10000005]; struct node{ int l,r; bool beCovered; }; int cnt; node a[MAXN*8];//*4 会RE ?? void

bnu36905 Nested Segments 离散化+线段树

bnu36905 Nested Segments 离散化+线段树区间更新 也可以用离散化+set(或双向链表) #include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <queue> #include <string> #include <set> #include <stack> #include &l

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

POJ 2528 Mayor&#39;s posters(线段树区间染色+离散化或倒序更新)

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