CF1834 D. Survey in Class [离线+权值线段树]

传送门:CF

[前题提要]:思维难度不高,但感觉维护的技巧性较强,故记录一下


不难想到枚举每一个区间作为我们的高度最大的区间.
这样我们的问题就变成了对于剩下的其他区间,如何找到高度最小的区间.然后对于每一种情况,都统计一下贡献即可.

仔细推敲之后,不难发现,我们只有将当前的区间中的所有数都提问一次,此时的是最优的.为什么呢,下面来简单证明一下这个贪心.不妨假设当前的区间为 [ l , r ] [l,r] [l,r],那么对于在区间外的数字,我们不应该将其加入我们的提问数字,因为对于区间外的数字,我们的最大值区间并不会减少1贡献,对于其他区间来说,他们有两种情况,要么因为此增加1贡献,要么因为此减少1贡献,我们会发现,不管是哪种情况,我们此时的 M a x − M i n Max-Min MaxMin都不会增加.所以此时是不优的.类似的,我们会发现对于区间内的数字,如果我们不提问该数字,我们Max区间会减少1贡献,其他区间要么减少1贡献,要么不减,无论那种情况,发现都是不优.

所以对于枚举的区间 [ l , r ] [l,r] [l,r],我们此时的提问数字必然是 l , l + 1 , . . . , r l,l+1,...,r l,l+1,...,r,考虑此时如何找到最小贡献区间.我们得用 l o g log log以内的算法找到该区间,不难想到二分.所以按照套路,先对所有区间按左端点进行排序,会发现存在大致四种情况.在分类之前,我们得先简单分析一下对于另外一个区间 [ l ′ , r ′ ] [l',r'] [l,r],我们的贡献是什么.假设我们的 [ l , r ] [l,r] [l,r]长度为 x x x,两个区间交叉部分为 y y y,我们此时的贡献就是 x − ( y − ( x − y ) ) x-(y-(x-y)) x(y(xy)),也就是 2 ∗ x − 2 ∗ y 2*x-2*y 2x2y.ok,有了这个之后,我们就可以进行分类了.

  1. 区间 [ l ′ , r ′ ] [l',r'] [l,r], l ′ > r ∣ ∣ r ′ < l l'>r||r'<l l>r∣∣r<l,也就是和上述区间没有交叉
  2. 区间 [ l ′ , r ′ ] [l',r'] [l,r], l ′ ≥ l & & l ′ ≤ r & & r ′ ≥ l & & r ′ ≤ r l'\geq l\&\&l'\leq r \&\&r'\geq l\&\&r'\leq r ll&&lr&&rl&&rr,也就是被上述区间包含的情况
  3. 区间 [ l ′ , r ′ ] [l',r'] [l,r], l ′ ≥ l & & l ′ ≤ r & & r ′ ≥ r l'\geq l\&\&l'\leq r \&\&r'\geq r ll&&lr&&rr,部分交叉
  4. 区间 [ l ′ , r ′ ] [l',r'] [l,r], l ′ ≤ l & & r ′ ≥ l & & r ′ ≤ r l'\leq l \&\&r'\geq l\&\&r'\leq r ll&&rl&&rr,部分交叉

对于第一种情况,很好解决,我们会发现显然贡献就是 2 ∗ x 2*x 2x,当然这种情况,也可以融入到 3 , 4 3,4 3,4一起进行解决.

对于第二种情况,我们会发现这种情况下的所有区间的右端点都是小于等于当前端点的.单单的二分难以解决这种情况,因为我们既需要关注左端点,又需要关注右端点.对于这种情况,我们可以对其进行离线.考虑对排完序后的序列从右往左进行枚举,然后使用权值线段树来维护.因为我们是从右往左进行枚举的,所以对于当前区间,我们所有满足左端点大于等于当前左端点的区间被记录.所以此时我们可以对所有区间的右端点来建一颗权值线段树,然后节点的贡献就是当前区间的长度.那么对于枚举到的区间来说,我们找到右端点小于当前右端点的所有节点的贡献的最小值即可.当前这种情况,整个区间都属于交叉部分,所以显然越小越好.

对于第三种情况,我们继承第二种情况的思考方式.同样从右往左加入区间,那么此时我们只要找到右端点大于等于当前区间的右端点的所有区间中左端点最大的那一个即可.此时我们就可以用这个左端点来计算出交叉部分.同样可以对右端点建一颗权值线段树,节点的贡献就是每一个区间的左端点,这样就可以轻松维护了.

对于第四种情况,维护方式同2,3.但是此时我们得从左往右进行枚举了.但是大致维护方式相同,所以就不再赘述了.

因为区间范围达到了 1 e 9 1e9 1e9,所以需要进行离散化.


下面是具体的代码部分:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls (rt<<1)
#define rs (rt<<1|1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {ll x=0,w=1;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';return x*w;
}
inline void print(__int128 x){if(x<0) {putchar('-');x=-x;}if(x>9) print(x/10);putchar(x%10+'0');
}
#define maxn 200010
#define int long long
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
struct Line{int l,r,id;bool operator < (const Line &rhs) const {if(l!=rhs.l) return l<rhs.l;else return r<rhs.r;}
}line[maxn];vector<int>v;
int find_pos(int x) {auto pos=lower_bound(v.begin(),v.end(),x)-v.begin()+1;return pos;
}
struct Segment_tree{int l,r,mx,mn;
}tree1[maxn<<2],tree2[maxn<<2];
void pushup(int rt,Segment_tree tree[]) {tree[rt].mx=max(tree[ls].mx,tree[rs].mx);tree[rt].mn=min(tree[ls].mn,tree[rs].mn);
}
void build(int l,int r,int rt,Segment_tree tree[]) {tree[rt].l=l;tree[rt].r=r;tree[rt].mx=-ll_INF;tree[rt].mn=ll_INF;if(l==r) {return ;}int mid=(l+r)>>1;build(lson,tree);build(rson,tree);pushup(rt,tree);
}
void update(int pos,int val,int rt,Segment_tree tree[]) {if(tree[rt].l==pos&&tree[rt].r==pos) {tree[rt].mx=max(tree[rt].mx,val);tree[rt].mn=min(tree[rt].mn,val);return ;}int mid=(tree[rt].l+tree[rt].r)>>1;if(pos<=mid) update(pos,val,ls,tree);else update(pos,val,rs,tree);pushup(rt,tree);
}
int query1(int l,int r,int rt,Segment_tree tree[]) {if(tree[rt].l==l&&tree[rt].r==r) {return tree[rt].mn;}int mid=(tree[rt].l+tree[rt].r)>>1;if(r<=mid) return query1(l,r,ls,tree);else if(l>mid) return query1(l,r,rs,tree);else return min(query1(l,mid,ls,tree),query1(mid+1,r,rs,tree));
}
int query2(int l,int r,int rt,Segment_tree tree[]) {if(tree[rt].l==l&&tree[rt].r==r) {return tree[rt].mx;}int mid=(tree[rt].l+tree[rt].r)>>1;if(r<=mid) return query2(l,r,ls,tree);else if(l>mid) return query2(l,r,rs,tree);else return max(query2(l,mid,ls,tree),query2(mid+1,r,rs,tree));
}
signed main() {int T=read();while(T--) {int n=read();int m=read();for(int i=1;i<=n;i++) {line[i].l=read();line[i].r=read();line[i].id=i;v.push_back(line[i].l);v.push_back(line[i].r);}sort(line+1,line+n+1);sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());//rightint Size=v.size();build(1,Size,1,tree1);build(1,Size,1,tree2);int ans=-ll_INF;for(int i=n;i>=1;i--) {int num=2*(line[i].r-line[i].l+1);int pos=find_pos(line[i].r);int num2=query2(pos,Size,1,tree2);int num3=query1(1,pos,1,tree1);if(num2>line[i].r) {if(num2!=-ll_INF) ans=max(ans,num);}else {if(num2!=-ll_INF) ans=max(ans,num-2*(line[i].r-num2+1));}if(num3!=ll_INF) ans=max(ans,num-2*num3);update(pos,line[i].r-line[i].l+1,1,tree1);update(pos,line[i].l,1,tree2);}//leftbuild(1,Size,1,tree1);build(1,Size,1,tree2);for(int i=1;i<=n;i++) {int num=2*(line[i].r-line[i].l+1);int pos=find_pos(line[i].l);int num2=query1(1,pos,1,tree1);if(num2<line[i].l) {if(num2!=ll_INF) ans=max(ans,num);}else {if(num2!=ll_INF) ans=max(ans,num-2*(num2-line[i].l+1));}update(pos,line[i].r,1,tree1);}cout<<ans<<endl;v.clear();}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/771726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LangChain核心模块 Model I/O——Prompts

Prompts ​ 语言模型的提示是用户提供的一组指令或输入&#xff0c;用于指导模型的响应&#xff0c;帮助模型理解上下文并生成相关且连贯的基于语言的输出&#xff0c;例如回答问题、完成句子或参与某项活动。对话。 关键问题 如何在LLMs中使用少量示例(few-shot examples)—…

Mathworks Matlab R2024a (24.1.0) Crack

MATLAB 是一种面向科学与工程计算的高级语言&#xff0c;允许以数学形式的语言编写程序&#xff0c;比BASIC、FORTRAN 和 C语言都要更加接近于我们书写数学计算公式的思维方式。可以说&#xff0c;用MATLAB 编写程序&#xff0c;就像是在草稿纸上排列公式和求解问题&#xff0c…

Aurora IP的Framing帧接口和Streaming流接口

本文介绍Aurora IP配置时要选择的接口类型以及两种接口类型之前的区别。 Aurora IP接口有两种模式&#xff1a;Framing帧接口&#xff0c;Streaming流接口 目前一直在用的都是Framing帧接口。 Framing帧接口和Streaming流接口的主要区别是什么呢&#xff1f; 顾名思义&#x…

什么是机器硬盘?

硬盘是电脑中的主要存储设备&#xff0c;能够进行长期的存储操作系统、软件和数据文件等内容。硬盘能够给电脑提供较大的物理和虚拟的存储空间&#xff0c;硬盘的主要参数就在于它的容量大小&#xff0c;硬盘主要是由一个或多个铝制或者是玻璃制的碟片组成的&#xff0c;碟片上…

国内用户掌握ChatGPT,你已超越万人!

在数字时代&#xff0c;掌握前沿技术往往意味着拥有更多的机遇和可能。ChatGPT&#xff0c;作为当前最热门的人工智能技术之一&#xff0c;已经证明了其在各个领域的广泛应用价值。但在中国&#xff0c;能熟练使用ChatGPT的人究竟领先了多少人&#xff1f;让我们深入探讨。>…

【Git】日志功能

1. git日志显示 # 显示前3条日志 git log -3# 单行显示 git log --oneline# 图表日志 git log --graph# 显示更改摘要 git log --stat# 显示更改位置 git log --patch 或 git log -p# 查看指定文件的提交历史记录 git log {filename}例子1&#xff1a;单行显示 例子2&#xff…

2024年最新阿里云服务器价格表_CPU内存+磁盘+带宽价格

2024年阿里云服务器租用费用&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核4G服务…

ManageEngine EventLog Analyzer: 功能丰富的日志分析工具

来自 Zoho Corp. 的 ManageEngine EventLog Analyzer 是一个小型应用程序&#xff0c;提供了许多功能。该产品采用无代理方式收集和分析机器生成的日志。该工具可以收集和规范化事件日志和机器数据&#xff0c;并在易于使用的基于 Web 的界面中提供分析、搜索、报告生成和存档等…

华院计算荣获CSDN“创新企业”和“年度创新产品与解决方案”大奖

日前&#xff0c;全国最大的专业开发者社区CSDN发布“2023中国开发者影响力年度榜单”&#xff0c;华院计算凭借其卓越的认知智能引擎平台荣获“创新企业”和“年度创新产品与解决方案”两项大奖。 CSDN 以数据为基础&#xff0c;经过个人或企业提交资料、层层筛选、深入调研、…

机器人干涉(碰撞)检测基础——Bresenham 直线算法

前言 Bresenham 直线算法是一种画线算法,用于确定应选择的n维栅格中的点,以形成两点之间直线的近似值。它通常用于在位图图像中(例如在计算机屏幕上)绘制线图元,因为它仅使用整数加法、减法和位移位,所有这些在历史上常见的计算机体系结构中都是非常便宜的操作。它是一种…

【Redis】数据类型、事务执行、内存淘汰策略

目录 数据类型 Redis事务执行步骤 步骤&#xff1a; redis内存淘汰策略 设置内存淘汰策略 1.设置配置文件 2.通过命令设置 数据类型 官网解释 Understand Redis data types | Redis 首先&#xff0c;Redis 的所有键都是字符串,常用的数据类型有 5 种&#xff1a;Strin…

【LeetCode周赛】第 390 场周赛

目录 3090. 每个字符最多出现两次的最长子字符串 简单3091. 执行操作使数据元素之和大于等于 K 中等3092. 最高频率的 ID 中等3093. 最长公共后缀查询 困难 3090. 每个字符最多出现两次的最长子字符串 简单 3090. 每个字符最多出现两次的最长子字符串 分析&#xff1a; 数据量…

SpringBoot整合WebService

WebService是一个SOA&#xff08;面向服务的编程&#xff09;的架构&#xff0c;它是不依赖于语言&#xff0c;不依赖于平台&#xff0c;可以实现不同的语言间的相互调用&#xff0c;通过Internet进行基于Http协议的网络应用间的交互。 其实WebService并不是什么神秘的东西&…

推荐一款电子翻页书制作软件

随着数字化时代的到来&#xff0c;电子书籍越来越受到人们的喜爱。而一款优秀的电子翻页书制作软件&#xff0c;则能够帮助你轻松制作出专业级的电子书&#xff0c;让你的阅读体验更加丰富多彩。 今天&#xff0c;我们就来为大家推荐一款优秀的电子翻页书制作软件——FLBOOK在线…

数据结构 --- 复杂度概念及计算讲解(时间复杂度,空间复杂度)

今天没有sao话&#xff0c;今天认真学习 一、时间复杂度 1、概念讲解 2、计算讲解 二、空间复杂度 1、概念讲解 2、计算讲解 三、常见复杂度对比 四、完结撒❀ 前言&#xff1a; 经常刷题的人都知道&#xff0c;我们在解决一道题时可能有多个解法&#xff0c;那么如何…

前端:利用生成器和迭代器实现分离逻辑

title: 前端&#xff1a;利用生成器和迭代器实现分离逻辑 date: 2024-03-05 23:31:12 categories: 前端 tags: 前端JavaScript 工作半年了常没时间、没动力学习新东西&#xff0c;每天就在忙着写业务逻辑&#xff0c;非常的枯燥。即使考虑到可以用新东西来实现某个需求&#x…

使用EasyYapi插件简化导出yapi接口

安装 &#xff1a; 关键配置&#xff1a; 其中的token在这里拿&#xff1a; 使用&#xff1a; 导出当前Controller下的所有api&#xff1a;使用下图命令可仅导出指定的api: 附&#xff1a;配置部分参考了idea&#xff1a;使用easyYapi插件导出yapi接口

在树莓派4B上安装Ubuntu Server 20

在树莓派4B上安装Ubuntu Server 20 树莓派是一个广受欢迎的小型单板计算机&#xff0c;它可以用于各种项目&#xff0c;从家庭自动化到网络服务器。Ubuntu Server 20是一个轻量级、高效的操作系统&#xff0c;非常适合在树莓派上运行。本文将指导你如何在树莓派上安装Ubuntu S…

Docker Stack(堆栈) 部署多服务集群,多服务编排

1、Docker Stack简介 Docker Stack(堆栈) 是在 Swarm 上管理服务堆栈的工具。而在以前文章docker swarm集群搭建 介绍的 Docker Swarm 只能实现对单个服务的简单部署&#xff0c;于是就引出了Docker Stack。 上面我们介绍到 docker-compose&#xff1a;可以在一台机器上使用…

Vue中如何实现动态改变字体大小

在Vue应用程序中&#xff0c;动态改变字体大小是一个常见的需求。这可以通过使用Vue的数据绑定功能和计算属性来实现。在本文中&#xff0c;我们将介绍如何在Vue中实现动态改变字体大小&#xff0c;并提供示例代码以帮助您更好地理解。 开始 在动态改变字体大小之前&#xff0…