51nod 1571 最近等对

题面

现在有一个序列 a1, a2, ..., an ,还有m个查询 lj, rj (1 ≤ lj ≤ rj ≤ n) 。对于每一个查询,请找出距离最近的两个元素 ax 和 ay (x ≠ y) ,并且满足以下条件:

· lj ≤ x, y ≤ rj;

· ax = ay。

两个数字的距离是他们下标之差的绝对值 |x − y| 。

Input

单组测试数据。

第一行有两个整数n, m (1≤n,m≤5*10^5),表示序列的长度和查询的次数。

第二行有n个整数a1,a2,...,an (-109≤ai≤109)。

接下来有m行,每一行给出两个整数lj,rj (1≤lj≤rj≤n)表示一个查询。

Output

对于每一个查询,输出最近的距离,如果没有相等的元素,输出-1。

Input示例

样例输入1

5 3

1 1 2 3 2

1 5

2 4

3 5

Output示例

样例输出1

1

-1

2

题解

离线之后,从左向右扫一遍,让每个值存储“当前已扫过的部分中,右边第一个与自己相等的点到自己的距离”,然后如果当前扫到的点是询问的右端点的话,就回答这个询问。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
bool read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
else if(c == EOF) return 0;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
return 1;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
} const int N = 500005;
int n, m, q, a[N], s[N], last[N], left[N], data[4*N], ans[N];
struct Query {
int id, l, r;
bool operator < (const Query &b) const{
return r < b.r;
}
} Q[N]; void build(int k, int l, int r){
if(l == r) return (void)(data[k] = INF);
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
data[k] = INF;
}
void change(int k, int l, int r, int p, int x){
if(l == r) return (void)(data[k] = x);
int mid = (l + r) >> 1;
if(p <= mid) change(k << 1, l, mid, p, x);
else change(k << 1 | 1, mid + 1, r, p, x);
data[k] = min(data[k << 1], data[k << 1 | 1]);
}
int query(int k, int l, int r, int ql, int qr){
if(ql <= l && qr >= r) return data[k];
int mid = (l + r) >> 1, ret = INF;
if(ql <= mid) ret = min(ret, query(k << 1, l, mid, ql, qr));
if(qr > mid) ret = min(ret, query(k << 1 | 1, mid + 1, r, ql, qr));
return ret;
} int main(){
read(n), read(q);
for(int i = 1; i <= n; i++)
read(a[i]), s[i] = a[i];
sort(s + 1, s + n + 1);
int m = unique(s + 1, s + n + 1) - s - 1;
for(int i = 1; i <= n; i++){
a[i] = lower_bound(s + 1, s + m + 1, a[i]) - s;
left[i] = last[a[i]];
last[a[i]] = i;
}
build(1, 1, n);
for(int i = 1; i <= q; i++)
Q[i].id = i, read(Q[i].l), read(Q[i].r);
sort(Q + 1, Q + q + 1);
for(int i = 1, j = 1; i <= n && j <= q; i++){
if(left[i]) change(1, 1, n, left[i], i - left[i]);
while(j <= q && i == Q[j].r){
ans[Q[j].id] = query(1, 1, n, Q[j].l, Q[j].r);
j++;
}
}
for(int i = 1; i <= q; i++)
write(ans[i] < INF ? ans[i] : -1), enter;
return 0;
}

51nod 1571 最近等对 | 线段树 离线的更多相关文章

  1. 51nod 1463 找朋友(线段树+离线处理)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序, ...

  2. 51nod 1364 最大字典序排列(线段树)

    1364 最大字典序排列基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字 ...

  3. 线段树+离线 hdu5654 xiaoxin and his watermelon candy

    传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足 ...

  4. 牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)

    前言 听说是线段树离线查询?? 做题做着做着慢慢对离线操作有点感觉了,不过也还没参透,等再做些题目再来讨论离线.在线操作. 这题赛后看代码发现有人用的树状数组,$tql$.当然能用树状数组写的线段树也 ...

  5. HDU 4638-Group(线段树+离线处理)

    题意: 给n个编号,m个查询每个查询l,r,求下标区间[l,r]中能分成标号连续的组数(一组内的标号是连续的) 分析: 我们认为初始,每个标号为一个组(线段树维护区间组数),从左向右扫序列,当前标号, ...

  6. HDU 4630-No Pain No Game(线段树+离线处理)

    题意: 给你n个数的序列a,q个询问,每个询问给l,r,求在下标i在[l,r]的区间任意两个数的最大公约数中的最大值 分析: 有了hdu3333经验,我们从左向右扫序列,如果当前数的约数在前面出现过, ...

  7. HDU 4288 Coder 【线段树+离线处理+离散化】

    题意略. 离线处理,离散化.然后就是简单的线段树了.需要根据mod 5的值来维护.具体看代码了. /* 线段树+离散化+离线处理 */ #include <cstdio> #include ...

  8. SPOJ--K-query (线段树离线) 离线操作解决一些问题

    K-query Given a sequence of n numbers a1, a2, ..., an and a number of k- queries. A k-query is a tri ...

  9. lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增

    https://www.luogu.org/problemnew/show/P3379 1.欧拉序+rmq(st) /* 在这里,对于一个数,选择最左边的 选择任意一个都可以,[left_index, ...

随机推荐

  1. [Processing]在画布上写文本

    准备工作 这一步只是我强迫症犯了哈,这个随意,画几根线而已.每一小格10个像素,中格50,大格100像素 void setup() { size(,); } void draw() { backgro ...

  2. HIVE函数的UDF、UDAF、UDTF

    一.词义解析 UDF(User-Defined-Function) 一进一出 UDAF(User- Defined Aggregation Funcation) 多进一出 (聚合函数,MR) UDTF ...

  3. CocoStuff—基于Deeplab训练数据的标定工具【一、翻译】(未完)

    一.CocoStuff简介 CocoStuff是一款为deeplab设计的,运行在Matlab中的语义标定工具,其标定结果和结合Deeplab训练出的结果均为mat文件格式,该项目源码已在github ...

  4. TCP协议数据包及攻击分析

    TCP/IP协议栈中一些报文的含义和作用 URG: Urget pointer is valid (紧急指针字段值有效) SYN: 表示建立连接 FIN: 表示关闭连接 ACK: 表示响应 PSH: ...

  5. SQL中读取Excel 以及 bpc语言

    --开启导入功能 reconfigure reconfigure --允许在进程中使用ACE.OLEDB.12 --允许动态参数 EXEC master.dbo.sp_MSset_oledb_prop ...

  6. linux获得命令使用帮助

    1. 内部命令: help CMD 2. 外部命令: CMD --help 3. 命令手册: manual(所有命令) man CMD 分章节: 1: 用户命令(User Commands - /bi ...

  7. 输入一个URL到页面呈现其中发生的过程-------http过程详解

    在我们点击一个网址,到它能够呈现在浏览器中,展示在我们面前,这个过程中,电脑里,网络上,究竟发生了什么事情. 服务器启动监听模式 那我们就开始了,故事其实并不是从在浏览器的地址栏输入一个网址,或者我们 ...

  8. PC端上必应词典与金山词霸的测评分析

    1.  介绍 随着英语学习越来越普及,基本上现在每位大学生的电脑上都会有一款便捷的英语查词软件,这次我们团队选择测评的 是微软必应词典(3.5.0.4311)和金山词霸(2014.05.16.044) ...

  9. JAVA第一次实验 ——凯撒密码

    课程:Java程序设计 班级:1352 姓名:黄伟业 学号:20135215 成绩:            指导教师:娄嘉鹏  实验日期:2015.4.15 实验密级: 预习程度:  实验时间:19: ...

  10. 编程之法section II: 2.2 和为定值的两个数

    ====数组篇==== 2.2 求和为定值的两个数: 题目描述:有n个整数,找出其中满足两数相加为target的两个数(如果有多组满足,只需要找出其中一组),要求时间复杂度尽可能低. 解法一: 思路: ...