题目链接

看题解觉得非常眼熟,总感觉做过非常非常类似的题啊,就是想不起来=v=。

似乎是这道...也好像不是。


\(Description\)

给定长为\(n\)的序列\(A_i\)。\(m\)次询问,每次给定\(l,r\),求\(\min_{l\leq i,j\leq r,i\neq j}|A_i-A_j|\)。

\(n\leq10^5,\ m\leq3\times10^5\)。

\(Solution\)

离线,把询问按右端点排序。

当右端点\(r=i\)时,考虑\(l\)在每个位置的贡献。

先只考虑\(j\lt i,\ A_j\geq A_i\)的情况。等会把所有数取反再做一次。

\(A_i\)的贡献就是,找到\(i\)左边第一个\(\geq A_i\)的数\(A_j\),给区间\([1,j]\)的答案和\(A_j-A_i\)取\(\min\)。然后找\(j\)左边第一个\(\geq A_i\)且\(\lt A_j\)的数\(A_{j'}\),更新区间\([1,j']\)...

注意前面区间是可以用\(A_j-A_{j'}\)做答案的,所以要满足\(A_{j'}-A_i\lt A_j-A_{j'}\ \Rightarrow\ A_{j'}\lt\frac{A_j+A_i}{2}\)。每次\(A_j\)会至少除以\(2\)(虽然会带个\(\frac{A_i}{2^k}\),不管它= =),所以只会找\(O(\log A)\)次。

找\(j'\)用主席树好了。复杂度是\(O(n\log n\log A)\)的。离散化一下就是\(O(n\log^2n)\)了。

(CF数据范围给的真心...nb...=v=)

PS:找第一个\(j\)可以直接单调栈=-=

关于具体如何找,\(i\)左边第一个\(\lt x\)的位置(这个数肯定\(\lt A_j\),所以不用管此时的\(j\)):以权值\(A_k\)从小到大为下标建主席树,每棵树\(T_k\)维护\(\leq A_k\)的位置有哪些。查一下\(i\)位置在\([A_i,x)\)权值中的排名\(rk\),然后求\([A_i,x)\)中排名\(rk-1\)的位置就可以惹。

前缀修改最小值,单点查询,可以换成树状数组单点修改,后缀查询最小值。

然后这个写法似乎非常丑...完全比不过线段树+set的一个写法...=v=

发现CQzhangyu的码风和我有点类似啊,于是抄的非常开心qwq。

似乎有个非常nb的大概\(\log^3\)的线段树做法...不看了...


//982ms	28900KB
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define MAXIN 500000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5,INF=0x7fffffff; int A[N],root[N],pos[N],rk[N],ref[N],Ans[N*3]/*3n!!!*/;
char IN[MAXIN],*SS=IN,*TT=IN;
struct Quries
{
int l,r,id;
inline bool operator <(const Quries &x)const
{
return r<x.r;
}
}q[N*3];
struct President_Tree
{
#define ls son[x][0]
#define rs son[x][1]
#define lson ls,son[y][0],l,m
#define rson rs,son[y][1],m+1,r
#define S N*18
int tot,sz[S],son[S][2];
#undef S
void Modify(int &x,int y,int l,int r,int p)
{
sz[x=++tot]=sz[y]+1;
if(l==r) return;
int m=l+r>>1;
p<=m?(rs=son[y][1],Modify(lson,p)):(ls=son[y][0],Modify(rson,p));
}
int GetRank(int x,int y,int l,int r,int p)//y-x
{
if(l==r) return sz[y]-sz[x];//1
int m=l+r>>1;
return p<=m ? GetRank(lson,p) : sz[son[y][0]]-sz[ls]+GetRank(rson,p);
}
int Find(int x,int y,int l,int r,int k)
{
if(l==r) return l;
int m=l+r>>1,t=sz[son[y][0]]-sz[ls];
return k<=t?Find(lson,k):Find(rson,k-t);
}
}T1;
struct BIT
{
int n,t[N];
#define lb(x) (x&-x)
inline void Init(int nn) {n=nn, memset(t,0x7f,n+1<<2);}
inline void Modify(int p,int v)
{
for(; p; p^=lb(p)) t[p]=std::min(t[p],v);
}
inline int Query(int p)
{
int res=INF;
for(; p<=n; p+=lb(p)) res=std::min(res,t[p]);
return res;
}
}T2; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline bool cmp(int a,int b)
{
return A[a]<A[b];
}
void Solve(const int n,const int Q)
{
static int sk[N];
for(int i=1; i<=n; ++i) pos[i]=i;
std::sort(pos+1,pos+1+n,cmp);
int cnt=0; T1.tot=0, T2.Init(n);
for(int i=1; i<=n; ++i) A[pos[i]]!=A[pos[i-1]]&&(ref[++cnt]=A[pos[i]]), rk[pos[i]]=cnt, T1.Modify(root[cnt],root[rk[pos[i-1]]],1,n,pos[i]);//root[rk[pos[i-1]]]
ref[0]=-INF, A[sk[0]=0]=INF;
for(int top=0,i=1,now=1; i<=n&&now<=Q; ++i)
{
while(A[sk[top]]<A[i]) --top;
int j=sk[top];
while(j)
{
T2.Modify(j,A[j]-A[i]);
if(A[i]==A[j]) break;
int p=std::upper_bound(ref+1,ref+1+cnt,A[i]+A[j]-1>>1)-ref-1;
if(ref[p]<A[i]) break;
int t=T1.GetRank(root[rk[i]-1],root[p],1,n,i);
if(t==1) break;
j=T1.Find(root[rk[i]-1],root[p],1,n,t-1);
}
sk[++top]=i;
while(q[now].r==i) Ans[q[now].id]=std::min(Ans[q[now].id],T2.Query(q[now].l)), ++now;
}
} int main()
{
const int n=read();
for(int i=1; i<=n; ++i) A[i]=read();
const int Q=read();
for(int i=1; i<=Q; ++i) q[i]=(Quries){read(),read(),i};
std::sort(q+1,q+1+Q), memset(Ans,0x7f,sizeof Ans);
A[0]=Ans[0], q[Q+1].r=N, Solve(n,Q);
for(int i=1; i<=n; ++i) A[i]=-A[i];
Solve(n,Q);
for(int i=1; i<=Q; ++i) printf("%d\n",Ans[i]); return 0;
}

Codeforces.765F.Souvenirs(主席树)的更多相关文章

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

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

  2. Codeforces 765F Souvenirs - 莫队算法 - 链表 - 线段树

    题目传送门 神速的列车 光速的列车 声速的列车 题目大意 给定一个长度为$n$的序列,$m$次询问区间$[l, r]$内相差最小的两个数的差的绝对值. Solution 1 Mo's Algorith ...

  3. 【CF765F】Souvenirs 主席树

    [CF765F]Souvenirs 题意:给你一个长度为n的序列{ai},有m个询问,每次询问给出l,r,问在所有$l\le x < y\le r$中,$|a_x-a_y|$的最小值是多少. $ ...

  4. Codeforces 893F(主席树+dfs序)

    在子树内和距离不超过k是一个二维限制,容易想到主席树,但主席树显然没法查最小值,因为不满足区间可减.kdtree和二维线段树可以干这事,但肯定会T飞.但事实上我们的问题有一个特殊性:对某个点x,查询其 ...

  5. Codeforces 765F Souvenirs

    time limit per test 3 seconds memory limit per test 512 megabytes input standard input output standa ...

  6. CodeForces - 960F Pathwalks —— 主席树(n棵线段树)

    题目链接:https://vjudge.net/problem/CodeForces-960F You are given a directed graph with n nodes and m ed ...

  7. 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )

    在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...

  8. Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)

    链接:http://codeforces.com/contest/484/problem/E 题意: 给你n个数的,每个数代表高度: 再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值: ...

  9. Codeforces Round #524 (Div. 2) F. Katya and Segments Sets(主席树)

    https://codeforces.com/contest/1080/problem/F 题意 有k个区间,区间的种类有n种,有m个询问(n,m<=1e5,k<=3e5),每次询问a,b ...

随机推荐

  1. error while loading shared libraries: libopencv_core.so.3.4: cannot open shared object file: No such file or directory

    1. 将CMakeLists.txt 文件中 find_package(OpenCV REQURED)补充完整为带版本号的:find_package(OpenCV 2.4.9 REQURED) 2. ...

  2. openGL learning

    1,basic env in linux : cmake_minimum_required(VERSION 2.8) project(CP_01) set(GLFW_HOME /home/gearsl ...

  3. 使用SpringSecurity体验OAuth2 (入门2)

    本文继续使用SpringSecurity从实战角度对OAuth2进行体验,上一篇 搭建了项目环境,并对配置做了初步分析,分析发现会有两套配置可能在影响OAuth,一个是由授权服务的启动类上的注解@En ...

  4. 虎牙直播弹幕转换字幕格式 基于Node.js 的 huya-danmu

    1 首先安装nodejs运行环境, 从 http://nodejs.cn/download/ 下载对应的版本 2 安装 huya-danmu 模块, https://github.com/BacooT ...

  5. .Net Core----关于MVC中TempData持久化问题

    最近在做mvc跨控制器传值的时候发现一个问题,就是有时候TempData的值为null,然后查阅了许多资料,发现了许多都是逻辑和原理什么的(想看原理可以查看原理的文章,本文是用法),但是真正解决的办法 ...

  6. nvm的使用

    nvm能下载并按照指定 的版本,还能切换已安装好的版本,相当的好用

  7. js前台计算两个日期的间隔时间(时间差)

    在后台传来两个时间字段,从中解析出两个字符串类型的日期格式 需要在前台解析出两个时间的间隔 这里采用获取两个日期的时间戳进行计算 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时 ...

  8. 基于Vue2.x的小米商城移动端项目

    初学vue已经有一段时间,为了检验自己的学习成果,决定做一个项目作为一个阶段性总结,项目花了差不多半个月时间,目前实现了7个页面,商城的主要功能基本实现,代码已经放到github上面. 这个项目把大部 ...

  9. 出错: IOException parsing XML document from ServletContext resource [/cn.mgy.conig]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/cn.mgy.conig]

    错误的详细内容: 严重: StandardWrapper.Throwable org.springframework.beans.factory.BeanDefinitionStoreExceptio ...

  10. SpringMVC:处理静态资源

    方法1.采用<mvc:default-servlet-handler/> 若将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕获WEB 容器的所有请 ...