CF-522-D-线段树

news/2024/5/18 21:53:28

522-D 题目大意

给定一个长为\(n\)的序列\(a\),现有\(q\)个查询,每个查询\(q_i\)给定\(l_i,r_i(1 \le l_i,r_i \le n)\),要你找出所有相等元素对\(a_x\)\(a_y(l_i \le x,y \le r_i)\)中,绝对值\(|x-y|\)的最小值。


Solution

考虑三个相等的元素\(a_x,a_y,a_z(x < y < z)\),对于一个区间包含这三个元素的询问,我们只需要考虑\(|x-y|\)\(|z-y|\)的大小,可以直接舍弃掉\(|z-x|\),由此我们可以注意到,只需要关注相等元素那些相邻的元素对即可。那么基于此,整个序列中最多只会有\(n-1\)的元素对需要考虑。

那么如何维护这写元素对对应的线段长度来回答询问呢?

一个朴素的想法是把询问离线下来,按左端点排序,扫描线处理。线段长度则这样维护,把每个点作为左端点时的对应的最短线段长度记录下来,然后整体丢到一个数据结构里面。扫描的时候,把扫过点对应的信息从数据结构里删除,回答询问的时候从集合里查询区间最小值。显然,可以用线段树来实现它。

剩下的只需要预处理出各个元素作为左端点时对应的右端点,再全部插入线段树中即可。

时间复杂度\(O(nlog^2n)\),预处理有一个离散化,因此是双\(log\)的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;const int N=5e5+10;
struct node{int l,r;int w;
}tr[N<<2];void build(int u,int l,int r){tr[u]={l,r,(int)1e9};if(l==r) return;int m=(l+r)>>1;build(u<<1,l,m);build(u<<1|1,m+1,r);
}void modify(int u,int l,int r,int k){if(l<=tr[u].l&&tr[u].r<=r){tr[u].w=k;return;}int m=(tr[u].l+tr[u].r)>>1;if(l<=m) modify(u<<1,l,r,k);if(r>m) modify(u<<1|1,l,r,k);tr[u].w=min(tr[u<<1].w,tr[u<<1|1].w);
}int query(int u,int l,int r){if(l<=tr[u].l&&tr[u].r<=r){return tr[u].w;}int m=(tr[u].l+tr[u].r)>>1;int res=1e9;if(l<=m) res=min(res,query(u<<1,l,r));if(r>m) res=min(res,query(u<<1|1,l,r));return res;
}int main(){ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n,m;cin>>n>>m;vector<int> a(n);for(int i=0;i<n;i++) cin>>a[i];vector<array<int,3>> q(m);for(int i=0;i<m;i++){cin>>q[i][0]>>q[i][1];q[i][2]=i;}sort(q.begin(),q.end());map<int,int> p;vector<int> nxt(n,-1);build(1,1,n);for(int i=n-1;~i;i--){if(p.count(a[i])){nxt[i]=p[a[i]];modify(1,nxt[i]+1,nxt[i]+1,nxt[i]-i);}p[a[i]]=i;}vector<int> ans(m);for(int i=0,j=0;i<n;i++){while(j<m&&q[j][0]==i+1){ans[q[j][2]]=query(1,q[j][0],q[j][1]);j++;}if(nxt[i]!=-1) modify(1,nxt[i]+1,nxt[i]+1,1e9);}for(int i=0;i<m;i++){if(ans[i]==1e9) ans[i]=-1;cout<<ans[i]<<'\n';}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

2. 基础配置

1. 配置文件格式 1.1 配置文件自动提示功能消失解决方案 ​​ 1.2 SpringBoot配置文件加载顺序(了解) application.properties > application.yml > application.yaml 1.3 注意事项 SpringBoot核心配置文件名为application SpringBoot内置属性过多,且所有属性集中…

Qt/C++音视频开发72-倍速推流/音视频同步倍速推流/不改变帧率和采样率/低倍速和高倍速

一、前言 最近多了个新需求,需要倍速推流,推流界的扛把子obs也有倍速推流功能,最高支持到两倍速。这里所说的倍速,当然只限定在文件,只有文件才可能有倍速功能,因为也只有文件才能倍速解码播放。实时视频流是不可能倍速的,因为没有时长,有时长的才可以按照播放进度来。…

Excel求解器使用教程

添加规则求解加载项创建excel文件,点击文件点击选项选择加载项->规则求解加载项->转到选择规则求解加载项->确定求解器所在位置---数据->规划求解在excel文档中填写相关的计算公式,用来求解点击规则求解,填写对应的目标,可变单元和约束,选择求解方法来求解通过…

虚拟机创建教程

虚拟机创建 创建虚拟机的时候,选择自定义,自己来创建虚拟机在虚拟机中,选择创建16.2.X版本的虚拟机,兼容性比较好在创建虚拟机的操作系统时,选择稍后安装操作系统,实测中如果选择其他的在安装过程中会跳过系统安装的部分阶段选择对应的系统和版本选择名称和安装位置,个人…

union 和union all 使用区别

union 和union all 把 查询user表前5条数据查询user表数据从第7条数据开始,查询两条 通过union来把两个sql中的数据合并到一张表中,只查询出一条数据,会把重复的数据去掉 通过union all查询 出现出了两条数据,不会去重

TypeError: Cannot read properties of undefined (reading trim)

运行时提示:TypeError: Cannot read properties of undefined (reading trim) 问题排查: 1、确认trim()属性是否存在,这个是js 去除字符串左右空格,属性是存在的 2、确认this.form.proxy_url是否存在 3、确认确认this.form.proxy_url的值是否为undefined和null 通过排查和打…

vue2 项目执行npm run serve 启动项目卡在24%一直不动

vue模板中添加了信息,应这样写:<div>接口管理</div>