CodeForces 765 F 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 线段树的更多相关文章
- Codeforces Round #765 Div.1 F. Souvenirs 线段树
题目链接:http://codeforces.com/contest/765/problem/F 题意概述: 给出一个序列,若干组询问,问给出下标区间中两数作差的最小绝对值. 分析: 这个题揭示着数据 ...
- 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 ...
- [Codeforces 316E3]Summer Homework(线段树+斐波那契数列)
[Codeforces 316E3]Summer Homework(线段树+斐波那契数列) 顺便安利一下这个博客,给了我很大启发(https://gaisaiyuno.github.io/) 题面 有 ...
- Buses and People CodeForces 160E 三维偏序+线段树
Buses and People CodeForces 160E 三维偏序+线段树 题意 给定 N 个三元组 (a,b,c),现有 M 个询问,每个询问给定一个三元组 (a',b',c'),求满足 a ...
- CodeForces 877E DFS序+线段树
CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...
- [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)
[Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...
- [Codeforces 1199D]Welfare State(线段树)
[Codeforces 1199D]Welfare State(线段树) 题面 给出一个长度为n的序列,有q次操作,操作有2种 1.单点修改,把\(a_x\)修改成y 2.区间修改,把序列中值< ...
- Codeforces 765F Souvenirs 线段树 + 主席树 (看题解)
Souvenirs 我们将询问离线, 我们从左往右加元素, 如果当前的位置为 i ,用一棵线段树保存区间[x, i]的答案, 每次更新完, 遍历R位于 i 的询问更新答案. 我们先考虑最暴力的做法, ...
- Educational Codeforces Round 73 (Rated for Div. 2)F(线段树,扫描线)
这道题里线段树用来区间更新(每次给更大的区间加上当前区间的权重),用log的复杂度加快了更新速度,也用了区间查询(查询当前区间向右直至最右中以当前区间端点向右一段区间的和中最大的那一段的和),也用lo ...
随机推荐
- macvtap使用教程
kubernetes一键安装 macvtap是虚拟机网络虚拟化常用的一种技术,当然容器也可以用. MACVTAP 的实现基于传统的 MACVLAN. 和 TAP 设备一样,每一个 MACVTAP 设备 ...
- TypeScript环境安装,以及配置idea开发环境
安装前准备 安装typescript需要用到npm管理工具,而npm是随同Node.js一起安装的包管理工具,所以要先安装Node 1.前往Node官网下载最新版安装包:http://nodejs.c ...
- Node.js 环境搭建及简单应用
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型.如果你想创建自己的服务,那么Node.js是一个非 ...
- cinder支持nfs快照
[问题描述] cinder后端设置为NFS,磁盘创建快照失败. 日志里面发现了这个错误: VolumeDriverException: Volume driver reported an error: ...
- android ——网络编程
一.WebView 这个View就是一个浏览器,用于展示网页的. 布局文件: <LinearLayout xmlns:android="http://schemas.android.c ...
- leetcode bug free
---不包含jiuzhang ladders中出现过的题.如出现多个方法,则最后一个方法是最优解. 目录: 1 String 2 Two pointers 3 Array 4 DFS &&am ...
- 2321. 【NOIP普及组T1】方程
2321. [NOIP普及组T1]方程 时间限制: 1000 ms 空间限制: 262144 KB 题目描述
- linux下搭建LJMT(图文版)
一. 安装VM14 1.1 安装虚拟机vm14(略) 输入序列号:AC5XK-0ZD4H-088HP-9NQZV-ZG2R4(可自行百度) 二. 安装centos详细步骤 2.1安装centos.( ...
- ansible之变量
一.常用系统变量 1. loop #表示循环,去读循环体里的变量固定使用{{item}},item是个字典对象item.key=value,例如如下playbook内容: --- - name: ...
- Zabbix-绘制动态拓扑图基础篇
一.实验环境 1.1 zabbix 4.0.2 二.实验需求介绍 公司希望网络拓扑能够动态反应物理接口的状态或者业务的状态,希望将网络拓扑显示到大屏上 三.Zabbix在绘制拓扑的优缺点 3.1 优点 ...