【题解】邻值查找 [CH1301]

传送门:邻值查找 \([CH1301]\) \([AcWing136]\)

【题目描述】

给定一个长度为 \(n\) 的序列 \(A\),\(A\) 中的数各不相同。

\(\forall i \in[2,n]\) 求 \(min _{j=1}^{j<i}|A_i−A_j|\) 取得最小值时的 \(j\)。若最小值点不唯一,则选择 \(A_j\) 值较小的那个。

【样例】

样例输入:
3
1 5 3 样例输出:
4 1
2 1

【数据范围】

\(100\%\) \(n \leqslant 10^5,|Ai| \leqslant 10^9\)


【分析】

正解链表。像我这种不会链表的蒟蒻就只能写线段树了 \(QAQ\) 。

先离散化,然后维护一颗权值线段树,先把 \(a[1]\) 加进去。

后面对于每个 \(i\),先查询前面已经有多个比它小的,设为 \(level\)。

此时序列中第 \(level\) 大的数即为 \(a[i]\) 的前驱,第 \(level+1\) 大的即为 \(a[i]\) 的后继(序列中 的数各不相同)。

两者取个最小,若相等则选前驱。

时间复杂度:\(O(nlogn)\) 。

线段树常数比较大,所以有点慢,但也能过。

【Code】

#include<algorithm>
#include<cstdio>
#include<map>
#define pl (p<<1)
#define pr (p<<1|1)
#define mid (L+R>>1)
#define Re register int
using namespace std;
const int N=1e5+3;
int x,y,z,n,k,t,cnt,asw,tmp,root,a[N],b[N];
struct QAQ{int g,l,r;}tr[N<<2];map<int,int>id;
inline void in(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
inline void build(Re p,Re L,Re R){//初始化建树
tr[p].l=L,tr[p].r=R;
if(L==R)return;
build(pl,L,mid),build(pr,mid+1,R);
}
inline void add(Re p,Re x,Re l,Re r){//单点修改
Re L=tr[p].l,R=tr[p].r;
if(L==R){++tr[p].g;return;}
if(x<=mid)add(pl,x,l,r);
else add(pr,x,l,r);
tr[p].g=tr[pl].g+tr[pr].g;
}
inline int ask(Re p,Re k){//查询第k大
if(tr[p].l==tr[p].r)return tr[p].r;
if(tr[pl].g>=k)return ask(pl,k);
else return ask(pr,k-tr[pl].g);
}
inline int ask_level(Re p,Re x){//查询小于等于x的个数
Re L=tr[p].l,R=tr[p].r;
if(L==R)return tr[p].g;
if(x<=mid)return ask_level(pl,x);
else return tr[pl].g+ask_level(pr,x);
}
int main(){
in(n);
for(Re i=1;i<=n;++i){
in(a[i]);
if(!id[b[i]=a[i]])id[a[i]]=i;
}
sort(b+1,b+n+1),build(1,1,n);
add(1,lower_bound(b+1,b+n+1,a[1])-b,1,n);
for(Re i=2;i<=n;++i){
k=lower_bound(b+1,b+n+1,a[i])-b;
Re level=ask_level(1,k-1);//查询小于a[i]的个数
if(level)asw=ask(1,level);//查找第level大(即前驱后继)
if(level+1<=i-1){
tmp=ask(1,level+1);//查找第level+1大(即a[i]后继)
if(!asw||abs(a[i]-b[asw])>abs(b[tmp]-a[i]))asw=tmp;
//只有小于才赋值,等于时选择最小的a[j](即a[i]前驱)
}
printf("%d %d\n",abs(a[i]-b[asw]),id[b[asw]]);
add(1,k,1,n);
}
}

【题解】邻值查找 [CH1301]的更多相关文章

  1. CH1301 邻值查找【set应用】

    1301 邻值查找 0x10「基本数据结构」例题 描述 给定一个长度为 n 的序列 A,A 中的数各不相同.对于 A 中的每一个数 A_i,求:min(1≤j<i) ⁡|A_i-A_j|以及令上 ...

  2. 0x13链表与邻接表之邻值查找

    题目链接:https://www.acwing.com/problem/content/138/ 参考链接:https://blog.csdn.net/sdz20172133/article/deta ...

  3. 1301 邻值查找(set 平衡树 | 链表)

    描述 给定一个长度为 n 的序列 A,A 中的数各不相同.对于 A 中的每一个数 A_i,求: min(1≤j<i) ⁡|A_i-A_j| 以及令上式取到最小值的 j(记为 P_i).若最小值点 ...

  4. map按value值查找——find_if的使用(转载)

    转载:http://www.cnblogs.com/xufeiyang/archive/2012/05/09/2491871.html CValueFind #ifndef _CVALUEFIND_H ...

  5. 【数据结构】 顺序表查找(折半查找&&差值查找)

    #include <stdio.h> #include <stdlib.h> #include <time.h> #define MAXSIZE 10 首先构造一个 ...

  6. 查找算法(3)--Interpolation search--插值查找

    1. 插值查找 (1)说明 在介绍插值查找之前,首先考虑一个新问题,为什么上述算法一定要是折半,而不是折四分之一或者折更多呢? 打个比方,在英文字典里面查“apple”,你下意识翻开字典是翻前面的书页 ...

  7. PHP 根据值查找键名

    array_search (PHP 4 >= 4.0.5, PHP 5) mixed array_search ( mixed $needle , array $haystack [, bool ...

  8. Java枚举-通过值查找对应的枚举

    一.背景 Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等. 最近工作中,对接了很多其他的系统,发现对接的同一个系统 ...

  9. C#算法设计查找篇之03-插值查找

    插值查找(Interpolation Search) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/701 访问. 插值 ...

随机推荐

  1. java斐波那契数列的顺序输出

    斐波那契数列,即1.1.2.3.5......,从第三个数开始包括第三个数,都为这个数的前两个数之和,而第一第二个数都为1. 下面是java输出斐波那契数列的代码: import java.util. ...

  2. IOS疯狂基础之观察者模式

    转自:http://blog.csdn.net/wudizhukk/article/details/8981535 一.KVO Key-Value Observing,它提供一种机制,当指定的对象的属 ...

  3. linux源代码获取

    Ubuntu获取 # which ls /bin/ls # dpkg -S /bin/ls coreutils: /bin/ls # apt-get source coreutils CentOS获取 ...

  4. 电信NBIOT 7 - 源码下载

    电信NBIOT 1 - 数据上行(中国电信开发者平台对接流程) 电信NBIOT 2 - 数据上行(中间件获取电信消息通知) 电信NBIOT 3 - 数据下行 电信NBIOT 4 - NB73模块上行测 ...

  5. MySQL的过滤(极客时间学习笔记)

    数据过滤 SQL的数据过滤, 可以减少不必要的数据行, 从而可以达到提升查询效率的效果. 比较运算符 在SQL中, 使用WHERE子句对条件进行筛选, 筛选的时候比较运算符是很重要. 上面的比较运算符 ...

  6. EM算法直观认识

    Expectation Maximization, 字面翻译为, "最大期望". 我个人其实一直都不太理解EM算法, 从我个人的渊源来看, 之前数理统计里面的参数估计, 也是没有太 ...

  7. 【Linux】-- 认识bash shell

    一.前言 我们知道管理整个计算机硬件的其实是系统的内核,这个内核是需要被保护的,所以我们一般用户就只能通过shell来跟内核通信,以让内核达到我们所想要达到的工作.那么Linux系统有多少shell可 ...

  8. Js中的对象、构造函数、原型、原型链及继承

    1.对象 在传统的面向过程的程序设计中,会造成函数或变量的冗余.而JS中对象的目的是将所有的具有相同属性或行为的代码整合到一起,形成一个集合,这样就会方便我们管理,例如: var person1={  ...

  9. 201871010101-陈来弟《面向对象程序设计(Java)》第十一周学习总结

    201871010101-陈来弟<面向对象程序设计(Java)>第十一周学习总结 实验九  泛型程序设计技术 实验时间 2019-11-8 第一部分:理论基础知识 1.什么是泛型类 泛型是 ...

  10. 201871010108-高文利《面向对象程序设计(java)》第四周学习总结

    项目 内容 这个作业属于哪个课程 <任课教师博客主页链接> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址> ht ...