Souvenirs

题意:给你n个数, m次询问, 对于每次一次询问, 求出询问区间内绝对值差值的最小值。

题解:先按查询的右端点从小到大sort一下,然后对于塞入一个数的时候, 就处理出所有左端点到目前位置的点, 然后查询。

首先对于一个区间 [L,now] 和 另一个区间来说 [l+1,now] 来说, 左边这个区间的ans值一定是 <= 右边这个区间的 ans 值, 因为左边这个区间包含右边这个区间, 所以对于[1,now]这个区间来说,端点值左边的区间里的ans 一定 小于右边的 ans。

然后具体操作是, 先建树, 对于每一个节点来说,都讲他包含的数都塞入这个节点, 再通过归并排序保证这些数是递增排列,并且将ans树的答案都设为INF。然后对所有的查询,离线操作, 按照右端点sort一下, 然后每次对于一个新的右端点, 我们去更新他们前面的所有左端点值, 同时我们更新前面区间的时候, 我们都先检查一下这个答案能不能更新里面的值, 如果不能就剪枝, 就剪枝, 然后如果要更新右部分区间的话,就先更新右部分,再更新左部分,因为每次更新完之后d就会变小, 所以如果先更新左边,可能会导致右边区间的答案没有更新。(d为每次更新遇到的最小的ans值, 因为是先往右边更新的, 然后更左边的区间一定包含右边的这个答案, 所以即使左边的答案能更新成小一点, 但是不能更小的时候, 更新了也没有意义, 因为会更小的答案在右边)。然后查询的时候直接查询这一段区间的答案就好了。

代码:

 #include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const LL mod = (int)1e9+;
const int N = 1e5 + ;
vector<int> vc[N<<];
int Min[N<<];
int a[N];
int n;
struct Node{
int l, r;
int id;
}q[N*];
bool cmp(Node x1, Node x2){
return x1.r < x2.r;
}
void Merge(int rt){
int i = , j = ;
int l = rt*, r = rt*+;
int szl = vc[l].size(), szr = vc[r].size();
while(i < szl && j < szr){
if(vc[l][i] < vc[r][j]) vc[rt].pb(vc[l][i]), i++;
else vc[rt].pb(vc[r][j]), j++;
}
while(i < szl) vc[rt].pb(vc[l][i]), i++;
while(j < szr) vc[rt].pb(vc[r][j]), j++;
}
void Build(int l, int r, int rt){
Min[rt] = INF;
if(l == r){
vc[rt].pb(a[l]);
return ;
}
int m = l+r >> ;
Build(lson);
Build(rson);
Merge(rt);
}
int Query(int l, int r, int rt, int L, int R){
if(L <= l && r <= R){
return Min[rt];
}
int ret = INF, m = l+r >> ;
if(L <= m) ret = min(ret, Query(lson,L,R));
if(m < R) ret = min(ret, Query(rson,L,R));
return ret;
}
vector<int>::iterator it;
void Update(int l, int r, int rt, int R, int v, int &d){
if(l == r){
Min[rt] = min(Min[rt], abs(v-vc[rt][]));
d = min(d, Min[rt]);
return ;
}
it = lower_bound(vc[rt].begin(), vc[rt].end(), v);
if((it == vc[rt].end() || *it-v >= d) && (it == vc[rt].begin() || v - *(--it) >= d)){
d = min(d, Query(, n, , l, R));
return ;
}
int m = l+r >> ;
if(R > m) Update(rson,R,v,d);
Update(lson,R,v,d);
Min[rt] = min(Min[rt*], Min[rt*+]);
}
int ans[N*];
int main(){
scanf("%d", &n);
for(int i = ; i <= n; i++) scanf("%d", &a[i]);
Build(,n,);
int m;
scanf("%d", &m);
for(int i = ; i <= m; i++) scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i;
sort(q+, q++m, cmp);
int r = ;
int d;
for(int i = ; i <= m; i++){
while(r < q[i].r) {
d = INF;
Update(, n, , r, a[r+], d);
r++;
}
ans[ q[i].id ] = Query(, n, , q[i].l, r);
}
for(int i = ; i <= m; i++){
printf("%d\n", ans[i]);
}
return ;
}

765F

CodeForces 765 F Souvenirs 线段树的更多相关文章

  1. Codeforces Round #765 Div.1 F. Souvenirs 线段树

    题目链接:http://codeforces.com/contest/765/problem/F 题意概述: 给出一个序列,若干组询问,问给出下标区间中两数作差的最小绝对值. 分析: 这个题揭示着数据 ...

  2. Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) F. Souvenirs 线段树套set

    F. Souvenirs 题目连接: http://codeforces.com/contest/765/problem/F Description Artsem is on vacation and ...

  3. [Codeforces 316E3]Summer Homework(线段树+斐波那契数列)

    [Codeforces 316E3]Summer Homework(线段树+斐波那契数列) 顺便安利一下这个博客,给了我很大启发(https://gaisaiyuno.github.io/) 题面 有 ...

  4. Buses and People CodeForces 160E 三维偏序+线段树

    Buses and People CodeForces 160E 三维偏序+线段树 题意 给定 N 个三元组 (a,b,c),现有 M 个询问,每个询问给定一个三元组 (a',b',c'),求满足 a ...

  5. CodeForces 877E DFS序+线段树

    CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...

  6. [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)

    [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...

  7. [Codeforces 1199D]Welfare State(线段树)

    [Codeforces 1199D]Welfare State(线段树) 题面 给出一个长度为n的序列,有q次操作,操作有2种 1.单点修改,把\(a_x\)修改成y 2.区间修改,把序列中值< ...

  8. Codeforces 765F Souvenirs 线段树 + 主席树 (看题解)

    Souvenirs 我们将询问离线, 我们从左往右加元素, 如果当前的位置为 i ,用一棵线段树保存区间[x, i]的答案, 每次更新完, 遍历R位于 i 的询问更新答案. 我们先考虑最暴力的做法, ...

  9. Educational Codeforces Round 73 (Rated for Div. 2)F(线段树,扫描线)

    这道题里线段树用来区间更新(每次给更大的区间加上当前区间的权重),用log的复杂度加快了更新速度,也用了区间查询(查询当前区间向右直至最右中以当前区间端点向右一段区间的和中最大的那一段的和),也用lo ...

随机推荐

  1. js实现字符串转JSON格式

    在浏览器前端实现字符串转JSON格式,有多种方法,总结如下: 方法1. js函数,eval() 语法: var obj = eval ("(" + txt + ")&qu ...

  2. ld: warning: directory not found for option ''

    iOS开发中经常遇到这样的警告,如图所示: 原因是存在未用到的目录. 解决方法:选择Build Settings,找到Search Paths中的Library Search Paths,如下图 删除 ...

  3. 解决:django.db.utils.OperationalError: unable to open database file

    这是一个从GitHub上下载的,一个网站项目的源码.想要在自己的电脑上运行,期间过程相当曲折,不过至此终于是完成了. 1.安装过程: python2->virtualenv->django ...

  4. Linux vim基本的使用方法

    一.vim 的三种模式 (1) 插入模式 在插入模式中,才能输入文字:要进入插入模式,可以按键 “i”:如果要进入插入模式时,直接切换到下一行,可以输入“o”: (2) 命令模式 在命令模式中,主要进 ...

  5. sql server 2008 外键的级联操作

    问题提出:现在我有三张表,学生Student,课程Course,成绩SC 1.  学生表Student,主键是学号Sno 2.  课程Course,主码是课程号Cno 3.  成绩SC,主码是Sno和 ...

  6. redis实现排行榜

    1 前言 实现一个排版榜,我们通常想到的就是mysql的order by 简单粗暴就撸出来了.但是这样真的优雅吗? 数据库是系统的瓶颈,这是众所周知的.如果给你一张百万的表,让你排序做排行榜,花费的时 ...

  7. 转载 | embed用法(网站中视频、音频的添加)

    网站中添加视频: <embed src="http://player.video.qiyi.com/390cf6c74450e4c70b7bd2d883169914/0/0/w_19r ...

  8. 1.2模板templates

    一.模板使用 1. 配置模板目录 如果命令行创建的项目,需要手动配置模板文件目录,如果是Pycharm创建的项目,则无需配置 在项目根目录下创建模板目录,比如叫 templates,后续开发模板文件会 ...

  9. 高速开车换底盘记:Windows 与 Linux 部署都抗住了,但修车任务艰巨

    抱歉,又是一篇流水账,在排查问题的焦头烂额中写博客的确是一个挑战,望大家见谅. 今天园友溪源More发了一篇博文博客园翻车启示录,而翻车之后的最新进展是——昨天下午我们又把 .net core 引擎的 ...

  10. java后端_百度一面

    参考: https://www.nowcoder.com/discuss/215891?type=2&order=0&pos=10&page=1 1.会啥框架.不会. 2.锁的 ...