IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> CF1555E Boring Segments题解--zhengjun -> 正文阅读

[数据结构与算法]CF1555E Boring Segments题解--zhengjun

题目大意

给你 n n n 个区间 [ l i , r i ] [l_i,r_i] [li?,ri?] 以及每个区间的权值 w i w_i wi?,要求选择一些区间出来覆盖区间 [ 1 , m ] [1,m] [1,m] (要求区间首尾相接),求选择的区间的 w w w 的极差的最小值。

思路

看到极差的最小值,想到二分,但不会验证,放弃!

然后分析了一下,这个首尾相接就很难受,我们可以把所有区间的右端点都减一(包括区间 [ 1 , m ] [1,m] [1,m] ),就不需要首尾相接了,只要把每个点都覆盖到就好了。

接着我们考虑,最后选出来的区间的 w w w 如果在 [ a , b ] [a,b] [a,b] 之间的话,那么验证的话只要看看所有 w w w [ a , b ] [a,b] [a,b] 之间的区间能否覆盖所有点就好了。

但是这样枚举 [ a , b ] [a,b] [a,b] 这个区间的复杂度很高。

我们考虑优化这个过程。

首先,枚举一个 a a a 是逃不掉的,那么,可以发现,当 a a a 增长的时候, b b b 也在增长,所以可以从小到大枚举 a a a ,然后 two-pointers 将 b b b 向右移,然后验证是否能完全覆盖就好了。

验证能否覆盖所有点的话,那就维护一个线段树,维护区间中被覆盖到的区间数 || 最小的点 || 的被覆盖到的区间数(这句话有点难理解,但真的很重要,停顿都标好了(* ^ ▽ ^ *)),然后就直接线段树上区间加,查询区间 [ 1 , m ? 1 ] [1,m-1] [1,m?1] 的最小值就好了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
void read(){}
template<typename _Tp,typename... _Tps>
void read(_Tp &x,_Tps &...Ar){
	x=0;char c=getchar();bool flag=0;
	while(c<'0'||c>'9')flag|=(c=='-'),c=getchar();
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
	if(flag)x=-x;
	read(Ar...);
}
const int N=3e5+10,M=1e6+10;
int n,m;
struct zj{
	int l,r,w;
	bool operator < (const zj &x)const{
		return w<x.w;
	}
}a[N];
int minx[M<<2],f[M<<2];
void pushup(int rt){
	minx[rt]=min(minx[rt<<1],minx[rt<<1|1]);
}
void pushdown(int rt){
	if(f[rt]){
		minx[rt<<1]+=f[rt];
		minx[rt<<1|1]+=f[rt];
		f[rt<<1]+=f[rt];
		f[rt<<1|1]+=f[rt];
		f[rt]=0;
	}
}
void update(int l,int r,int rt,int head,int tail,int x){
	if(head<=l&&r<=tail)return minx[rt]+=x,f[rt]+=x,void();
	int mid=(l+r)>>1;pushdown(rt);
	if(head<=mid)update(l,mid,rt<<1,head,tail,x);
	if(mid<tail)update(mid+1,r,rt<<1|1,head,tail,x);
	pushup(rt);
}
int query(){
	return minx[1];
}
int get(){
	int i,now=0,ans=0x3f3f3f3f;
	for(read(n,m),m--,i=1;i<=n;i++)read(a[i].l,a[i].r,a[i].w),a[i].r--;//就像我说的那样
	for(sort(a+1,a+1+n),i=1;i<=n;i++){
		while(now<=n&&query()==0)now++,now<=n?(a[now].l<=a[now].r?update(1,m,1,a[now].l,a[now].r,1):void()):void();//确保 now<=n
		if(now<=n)ans=min(ans,a[now].w-a[i].w);//如果 now>n 说明不可能完全覆盖了
		update(1,m,1,a[i].l,a[i].r,-1);//区间内所有点的覆盖的区间数都少了 1
	}
	return printf("%d",ans),0;
}
int main(){
	return get();
}

谢谢–zhengjun

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:44:55  更:2021-08-01 14:46:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:41:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码