离散化——目的是压缩区间范围——优化线段树
区间覆盖问题——传统的cover数组再加上——这个题目的特殊性——计算的是最终能看到海报的数量——所以节点的值在这里我的含义是第几张海报覆盖了这个节点
好,看一下准备工作
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
#define lson i << 1,left,mid
#define rson i << 1 | 1,mid + 1,right
const int Max = 20010;
int ans;
int vis[Max];
struct Line{
int point;
int num;
}line[Max];
bool cmp(Line a,Line b)
{
return a.point < b.point;
}
int poster[Max / 2][2];
int t[Max << 2];根据题目开20000+
vis数组,line结构体,cmp函数,poster都是为了离散化处理并存储海报x轴的左右端点
t树组就是树了
for(int i = 1;i <= n;i++)
{
scanf("%d%d",&poster[i][0],&poster[i][1]);
line[i * 2 - 1].point = poster[i][0];
line[i * 2 - 1].num = -i;//左
line[i * 2].point = poster[i][1];
line[i * 2].num = i;//右
}
sort(line + 1,line + 2 * n + 1,cmp);
int flag = -0x3f3f;
int N = 0;
for(int i = 1;i <= 2 * n;i++)
{
if(line[i].point != flag)
{
N++;
flag = line[i].point;
}
if(line[i].num < 0)poster[-line[i].num][0] = N;
else poster[line[i].num][1] = N;
}离散化要为每一个节点都赋值,所以要2 * n
结构体的point的存储的是原来的x坐标,num存储的是一种映射| i |代表第几张海报,如果point为左端点,那么做个标记-i右端点为+i;
最后自定义排好序后,定义一个映射——N
对于每一个原来的端点都能映射回去,对于每一个不重复的端点N++
最后得到的N就是线段树需要的维护的宽度
接着常规的建树
void build(int i,int left,int right)
{
t[i] = 0;
if(left == right)return;
int mid = (left + right) >> 1;
build(lson);
build(rson);
}然后开始从头到尾贴海报
for(int i = 1;i <= n;i++)
{
//cout<<poster[i][0]<<" "<<poster[i][1]<<endl;
update(1,1,N,poster[i][0],poster[i][1],i);
}update要更新节点的值,和lazy标记的思想一样,我们不会把海报覆盖的长度一直维护到叶子节点,一旦找到最小包容区间就会停止,在更新这张海报的过程中,会顺便传递前面海报的lazy标记
void pd(int i)
{
if(t[i])
{
t[i << 1] = t[i];
t[i << 1 | 1] = t[i];
t[i] = 0;
}
}
void update(int i,int left,int right,int le,int re,int v)
{
if(le <= left && right <= re )
{
t[i] = v;
return;
}
pd(i);
int mid = (left + right) >> 1;
if(le <= mid) update(lson,le,re,v);
if(re > mid)update(rson,le,re,v);
}定义了vis数组开始查询能看到几张,就是代表能找到几个值不同的节点
void query(int i,int left,int right)
{
if(t[i] != 0)
{
if(!vis[t[i]])
{
vis[t[i]] = 1;
ans++;
}
return;
}
if(left == right)return;
int mid = (left + right) >> 1;
query(lson);
query(rson);
}注意这里从上往下找,一旦找到了不为零的节点的值,那么就可以return了,因为他的子节点没有必要再去往下找了,那些都是已经被覆盖的地方了
本文介绍了一种利用离散化技术和线段树解决区间覆盖问题的方法,通过优化数据结构来提高效率。详细解释了如何进行离散化处理,并结合线段树实现高效的查询与更新操作。
605

被折叠的 条评论
为什么被折叠?



