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. openGL基本概念

    OpenGL自身是一个巨大的状态机(State Machine):一系列的变量描述OpenGL此刻应当如何运行.OpenGL的状态通常被称为OpenGL上下文(Context).我们通常使用如下途径去 ...

  2. 当面对会反制遭破解装置的App该如何顺利提取数据

    在检测App的过程之中,总会遇到比较棘手的,以”侦测是否遭破解的装置”为例,便会是个不好处理的状况.当App具备侦测装置是否已遭Root时,一旦发现装置已遭破解,便会停止运行,等于是只准安装及运行在未 ...

  3. SQLServer2000同步复制技术实现步骤

    SQLServer2000同步复制技术实现步骤 一. 预备工作 1.发布服务器,订阅服务器都创建一个同名的windows用户,并设置相同的密码,做为发布快照文件夹的有效访问用户 --管理工具 --计算 ...

  4. 进军pc市场 华为剑走偏锋可有戏?

    尽管官方并未正式公布,但在前段时间,华为将要进军PC市场的消息在业内传得沸沸扬扬,据知情人士曝料,其第一款个人电脑将在今年4月上线.而华为将进军PC市场的消息,对其他智能手机厂商来说又意味着什么呢? ...

  5. shardingjdbc 强制路由走主库查询实时数据 避免主从同步数据延迟

    @Beanpublic shardingsphere.demo.entity.Order order(){ shardingsphere.demo.entity.Order order=new Ord ...

  6. 【Java例题】2.8 解一元二次方程

    8.解一元二次方程. 输入一元二次方程的a,b,c三个系数,解一元二次方程 ax^2+bx+c=0,输出两个根 package study; import java.util.Scanner; pub ...

  7. 如何获取app中的toast

    前言 Toast是什么呢?在这个手机飞速发展的时代,app的种类也越来越多,那们在日常生活使用中,经常会发现,当你在某个app的输入框输入非法字符或者非法执行某个流程时,经常看到系统会给你弹出一个黑色 ...

  8. 一文了解java异常机制

    1.异常的概述 1.1什么是异常? 异常:程序在运行过程中发生由于外部问题导致的程序异常事件,发生的异常会中断程序的运行.(在Java等面向对象的编程语言中)异常本身是一个对象,产生异常就是产生了一个 ...

  9. JavaScript数据结构——队列的实现与应用

    队列与栈不同,它遵从先进先出(FIFO——First In First Out)原则,新添加的元素排在队列的尾部,元素只能从队列头部移除. 我们在前一篇文章中描述了如何用JavaScript来实现栈这 ...

  10. 深入理解ES6之——代理和反射(proxy)

    通过调用new proxy()你可以创建一个代理来替代另一个对象(被称为目标),这个代理对目标对象进行了虚拟,因此该代理与该目标对象表面上可以被当做同一个对象来对待. 创建一个简单的代理 当你使用Pr ...