Codeforces 765F Souvenirs
Artsem is on vacation and wants to buy souvenirs for his two teammates. There are n souvenir shops along the street. In i-th shop Artsem can buy one souvenir for ai dollars, and he cannot buy more than one souvenir in one shop. He doesn't want to introduce envy in his team, so he wants to buy two souvenirs with least possible difference in price.
Artsem has visited the shopping street m times. For some strange reason on the i-th day only shops with numbers from li to ri were operating (weird? yes it is, but have you ever tried to come up with a reasonable legend for a range query problem?). For each visit, Artsem wants to know the minimum possible difference in prices of two different souvenirs he can buy in the opened shops.
In other words, for each Artsem's visit you should find the minimum possible value of |as - at| where li ≤ s, t ≤ ri, s ≠ t.
The first line contains an integer n (2 ≤ n ≤ 105).
The second line contains n space-separated integers a1, ..., an (0 ≤ ai ≤ 109).
The third line contains the number of queries m (1 ≤ m ≤ 3·105).
Next m lines describe the queries. i-th of these lines contains two space-separated integers li and ri denoting the range of shops working on i-th day (1 ≤ li < ri ≤ n).
Print the answer to each query in a separate line.
8
3 1 4 1 5 9 2 6
4
1 8
1 3
4 8
5 7
0
1
1
3
树套树 线段树+set 脑洞题
将询问按右端点从小到大排序。从左向右扫描,每次用当前点x更新从1到x位置的答案,然后回答所有右端点在x的询问。
我们可以用线段树更新每个位置答案的时候,这样复杂度显然比暴力更……劣了(可能需要遍历每个位置)。
不过我们可以给线段树加一些剪枝。当用a[x]更新区间[L,R]的时候,设当前最优答案是nowans 如果[L,R]区间内没有在a[x]-nowans ~ a[x]+nowans范围内的数,就不往深层更新了。
如何查找线段树区间内有哪些数?结点上挂个平(s)衡(e)树(t)即可。
↑为了让这个剪枝正确,更新的时候必须先更新线段树右区间再更新左区间。
/*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<set>
using namespace std;
const int INF=1e9;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct node{
int f;
set<int>st;
}t[mxn<<];
int a[mxn];
set<int>::iterator it,it2;
struct query{
int L,R;
int id;
bool operator < (const query &b)const{
return (R==b.R && L<b.L) || R<b.R;
}
}q[mxn];
int ans[mxn];
int n,Q;
#define ls rt<<1
#define rs rt<<1|1
void Build(int l,int r,int rt){
t[rt].f=INF;
for(int i=l;i<=r;i++)t[rt].st.insert(a[i]);
if(l==r)return;
int mid=(l+r)>>;
Build(l,mid,ls);Build(mid+,r,rs);
it=t[rt].st.begin();
it2=it;it2++;
for(;it2!=t[rt].st.end();it++,it2++){
t[rt].f=min(t[rt].f,abs(*it2-*(it)));
}
return;
}
int query(int L,int R,int l,int r,int rt){
// printf("L:%d R:%d l:%d r:%d rt:%d f:%d\n",L,R,l,r,rt,t[rt].f);
if(L<=l && r<=R)return t[rt].f;
int mid=(l+r)>>;int res=INF;
if(L<=mid)res=min(res,query(L,R,l,mid,ls));
if(R>mid)res=min(res,query(L,R,mid+,r,rs));
return res;
}
int nowans;
void update(int pos,int v,int l,int r,int rt){
if(l==r){
nowans=min(nowans,abs(a[l]-v));
t[rt].f=min(t[rt].f,nowans);
}
it=t[rt].st.lower_bound(v);
if(it!=t[rt].st.begin()){it2=it;it2--;}
if((it==t[rt].st.begin() || *(it2)<=v-nowans)&&(it==t[rt].st.end() || *(it)>=v+nowans)){
nowans=min(nowans,query(l,r,,n,));
return;
}
int mid=(l+r)>>;
if(pos>mid)
update(pos,v,mid+,r,rs);
update(pos,v,l,mid,ls);
t[rt].f=min(t[ls].f,t[rs].f);
return;
}
void solve(){
int i,j;
int hd=;
for(i=;i<=Q;i++){
while(hd<q[i].R){
nowans=INF; update(hd,a[hd+],,n,); hd++;
}
ans[q[i].id]=query(q[i].L,q[i].R,,n,);
}
for(i=;i<=Q;i++)printf("%d\n",ans[i]);
return;
}
int main(){
int i,j;
n=read();
for(i=;i<=n;i++)a[i]=read();
Q=read();
Build(,n,);
for(i=;i<=Q;i++){
q[i].L=read();q[i].R=read();q[i].id=i;
}
sort(q+,q+Q+);
solve();
return ;
}
Codeforces 765F Souvenirs的更多相关文章
- Codeforces 765F Souvenirs - 莫队算法 - 链表 - 线段树
题目传送门 神速的列车 光速的列车 声速的列车 题目大意 给定一个长度为$n$的序列,$m$次询问区间$[l, r]$内相差最小的两个数的差的绝对值. Solution 1 Mo's Algorith ...
- Codeforces 765F Souvenirs 线段树 + 主席树 (看题解)
Souvenirs 我们将询问离线, 我们从左往右加元素, 如果当前的位置为 i ,用一棵线段树保存区间[x, i]的答案, 每次更新完, 遍历R位于 i 的询问更新答案. 我们先考虑最暴力的做法, ...
- Codeforces.765F.Souvenirs(主席树)
题目链接 看题解觉得非常眼熟,总感觉做过非常非常类似的题啊,就是想不起来=v=. 似乎是这道...也好像不是. \(Description\) 给定长为\(n\)的序列\(A_i\).\(m\)次询问 ...
- 【codeforces 765F】 Souvenirs
http://codeforces.com/problemset/problem/765/F (题目链接) 题意 给出$n$个数的序列,$m$次询问,每次查询区间$[l,r]$之间相差最小的两个数的差 ...
- 【codeforces 765F】Souvenirs
Description Artsem is on vacation and wants to buy souvenirs for his two teammates. There are n souv ...
- Souvenirs CodeForces - 765F (好题)
大意: 给定序列$a$, $m$个询问$[l,r]$, 回答$[l,r]$内最接近的两个数的差. 考虑离线, 枚举右端点, 每个点维护左端点的贡献, 对于新添一个点$a_r$, 只考虑左侧点比$a_r ...
- codeforces选做
收录了最近本人完成的一部分codeforces习题,不定期更新 codeforces 1132E Knapsack 注意到如果只使用某一种物品,那么这八种物品可以达到的最小相同重量为\(840\) 故 ...
- 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 765 F Souvenirs 线段树
Souvenirs 题意:给你n个数, m次询问, 对于每次一次询问, 求出询问区间内绝对值差值的最小值. 题解:先按查询的右端点从小到大sort一下,然后对于塞入一个数的时候, 就处理出所有左端点到 ...
随机推荐
- Alpha 冲刺10
队名:日不落战队 安琪(队长) 今天完成的任务 整理项目. okhttp学习第四弹. 明天的计划 okhttp学习第五弹. 阶段反思. 睡觉. 还剩下的任务 个人信息数据get. 遇到的困难 困难:好 ...
- [图算法] 1003. Emergency (25)
As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...
- LR之Java Vuser II
最近项目待压测的服务端协议使用的是java的Netty框架开发,而传输的业务数据使用了google protobuf进行序列化,然后通过tcp数据流与客户端通讯.这一次的压测脚本决定使用LR的java ...
- c 读取文本
#include <stdio.h> #include <stdlib.h> #include <string.h> #define max 10 #define ...
- mysql项目路径URL编码
jdbc_url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncodi ...
- 如何更好的使用JAVA线程池
这篇文章结合Doug Lea大神在JDK1.5提供的JCU包,分别从线程池大小参数的设置.工作线程的创建.空闲线程的回收.阻塞队列的使用.任务拒绝策略.线程池Hook等方面来了解线程池的使用,其中涉及 ...
- 【C++】不要在构造函数或析构函数内调用虚函数
这个问题来自于<Effective C++>条款9:永远不要在构造函数或析构函数中调用虚函数 . 假设有如下代码: class Transaction {// 所有交易的基类 public ...
- LoadRunner脚本增强技巧之手动关联
个人认为LoadRunner的手动关联技巧可以看做参数化的一种,区别在与获取参数的来源不同. 一般的参数化:把脚本中一个写死的数值或者字符串用一个变量参数来代替,每次迭代的时候,从本地文件或者数据库中 ...
- DateTime Toxxx() 方法获取时间
直接上代码 static void Main(string[] args) { DateTime time = DateTime.Now; Console.WriteLine("ToFile ...
- 【bzoj4542】[Hnoi2016]大数 莫队算法
题目描述 给出一个数字串,多次询问一段区间有多少个子区间对应的数为P的倍数.其中P为质数. 输入 第一行一个整数:P.第二行一个串:S.第三行一个整数:M.接下来M行,每行两个整数 fr,to,表示对 ...