题意:链接

定义pos[i]表示i这个值在数组里的下标.

我们先用单调栈找到每个元素左边和右边第一个比它大的元素$l_i$和$r_i$,然后建一棵二叉树,我们就叫做maxtree吧 (upd:mdzz 这就是笛卡尔树)

每个点$i$的父亲是$pos[max(l_i,r_i)]$,如果是$r_i$比较大,那么$i$就是左儿子,$l_i$比较大同理。

当$i$是左儿子时,容易证出$pos[l_i]$在树上的位置就是$i$不停向上走时第一次向左上走遇到的点,反之亦然,设$gfa[x]$表示$x$连向的点中非$fa[x]$的点。

对于每个询问,我们先求出$x,y$的$lca t$,如果$t$不为$x$和$y$,那么最短路上要么经过$t$,要么经过$fa[t]$,这个也很好证(大概就是如果$t$是左儿子,那么$t$的左子树中的点不可能向$fa[t]$上边连边,右边同理)。

定义函数$dis(x,y)$表示$x$到$y$的最短路,其中$y$是$x$的祖先。

当$dep[g[fa[x]]]>=dep[y]$时,显然走$gfa$比较优,然后再在最后一步的时候两种方案取个$min$就行了,问题解决。

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,m;
int a[N];
int st[N],ll[N],rr[N],top;
int ch[N][2];
int fa[N][22],fs[N][22],dep[N];
void dfs(int x,int pr,int op)
{
if(ch[x][0])
{
fs[ch[x][0]][0]=x;
dep[ch[x][0]]=dep[x]+1;
if(op==0)
{
fa[ch[x][0]][0]=pr;
dfs(ch[x][0],pr,op);
}
else dfs(ch[x][0],x,op);
}
if(ch[x][1])
{
fs[ch[x][1]][0]=x;
dep[ch[x][1]]=dep[x]+1;
if(op==1)
{
fa[ch[x][1]][0]=pr;
dfs(ch[x][1],pr,op);
}
else dfs(ch[x][1],x,op);
}
return ;
}
void yu()
{
for(int i=1;i<=17;i++)
{
for(int j=1;j<=n;j++)
{
fa[j][i]=fa[fa[j][i-1]][i-1];
fs[j][i]=fs[fs[j][i-1]][i-1];
}
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=17;i>=0;i--)if(dep[fs[x][i]]>=dep[y])x=fs[x][i];
if(x==y)return x;
for(int i=17;i>=0;i--)
{
if(fs[x][i]!=fs[y][i])
{
x=fs[x][i];y=fs[y][i];
}
}
return fs[x][0];
}
int dis(int x,int y)
{
int ans=0;
for(int i=17;i>=0;i--)
{
if(dep[fa[x][i]]>=dep[y])
{
ans+=(1<<i);
x=fa[x][i];
}
}
if(!fa[x][0])return ans+dep[x]-dep[y];
return ans+min(dep[x]-dep[y],2);
}
int solve(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int t=lca(x,y);
if(t==y)return dis(x,y);
int tmp=dis(x,t)+dis(y,t);
if(t!=1)tmp=min(tmp,dis(x,fs[t][0])+dis(y,fs[t][0]));
return tmp;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
while(top&&a[st[top]]<a[i])top--;
if(top)ll[i]=st[top];
st[++top]=i;
}
top=0;
for(int i=n;i>=1;i--)
{
while(top&&a[st[top]]<a[i])top--;
if(top)rr[i]=st[top];
st[++top]=i;
}
ch[1][1]=n;
for(int i=2;i<=n-1;i++)
{
if(a[ll[i]]<a[rr[i]])ch[ll[i]][1]=i;
else ch[rr[i]][0]=i;
}
dep[1]=1;dfs(1,0,0);dfs(1,0,1);
yu();
int t1,t2;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&t1,&t2);
printf("%d\n",solve(t1,t2));
}
return 0;
}

  

ioi2018集训队自选题:最短路练习题的更多相关文章

  1. 简单数据结构题(from 钟子谦——IOI2018集训队自选题)

    简单数据结构题(from 钟子谦--IOI2018集训队自选题) 试题描述 给一棵 \(n\) 个点的树,点权开始为 \(0\) ,有 \(q\) 次操作,每次操作是选择一个点,把周围一圈点点权 \( ...

  2. 【BZOJ2622】[2012国家集训队测试]深入虎穴 次短路

    [BZOJ2622][2012国家集训队测试]深入虎穴 Description 虎是中国传统文化中一个独特的意象.我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物,例如“ ...

  3. 【UOJ347】【WC2018】通道 边分治 虚树 DP

    题目大意 给你三棵树,点数都是\(n\).求 \[ \max_{i,j}d_1(i,j)+d_2(i,j)+d_3(i,j) \] 其中\(d_k(i,j)\)是在第\(k\)棵数中\(i,j\)两点 ...

  4. 8月清北学堂培训 Day5

    今天是杨思祺老师的讲授~ 最短路练习题: POJ 1125 Stockbroker Grapevine 有 N 个股票经济人可以互相传递消息,他们之间存在一些单向的通信路径.现在有一个消息要由某个人开 ...

  5. 【6.24校内test】T3 棠梨煎雪

    [题目背景] 岁岁花藻檐下共将棠梨煎雪. 自总角至你我某日辗转天边. 天淡天青,宿雨沾襟. 一年一会信笺却只见寥寥数言. ——银临<棠梨煎雪> [问题描述] 扶苏正在听<棠梨煎雪&g ...

  6. 【LGR-065】洛谷11月月赛 III Div.2

    临近$CSP$...... 下午打了一发月赛,感觉很爽. 非常菜的我只做了前两题......然而听说前两题人均过...... 写法不优秀被卡到$#1067$...... T1:基础字符串练习题: 前缀 ...

  7. BZOJ_2622_[2012国家集训队测试]深入虎穴_最短路

    BZOJ_2622_[2012国家集训队测试]深入虎穴_最短路 Description 虎是中国传统文化中一个独特的意象.我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物 ...

  8. [转] ACM中国国家集训队论文集目录(1999-2009)

    国家集训队1999论文集 陈宏:<数据结构的选择与算法效率——从IOI98试题PICTURE谈起>来煜坤:<把握本质,灵活运用——动态规划的深入探讨>齐鑫:<搜索方法中的 ...

  9. ACM/ICPC 之 两道dijkstra练习题(ZOJ1053(POJ1122)-ZOJ1053)

    两道较为典型的单源最短路径问题,采用dijkstra解法 本来是四道练习题,后来发现后面两道用dijkstra来解的话总觉得有点冗余了,因此暂且分成三篇博客(本篇以及后两篇). ZOJ1053(POJ ...

随机推荐

  1. Linux lsof 命令

    lsof(list open files)是一个查看进程打开的文件的工具. 在 linux 系统中,一切皆文件.通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以 lsof 命令不仅可以查 ...

  2. Python - 列表解析式

    列表解析——用来动态地创建列表 [expr for iter_var in iterable if cond_expr] 例子一: map(lambda x: x**2, range(6)) [0, ...

  3. 软件工程——HelloWorld

    #include main(){ printf("Hello World\n"); }

  4. docker+redis 持久化配置(AOF)

    RDB持久化与AOF持久化简单描述 RDB:RDB使用快照的方式存储数据库中的内容,直接将所有键值对数据全部存入二进制文件.建议使用BGSAVE来进行备份,整个过程会新fork一个子进程来执行,不影响 ...

  5. 利用ss-redir加速服务器上国外服务的访问

    https://blog.microdog.me/2016/06/28/Speed-Up-Network-Accessing-To-Overseas-Services-On-Your-Server/

  6. [转帖]Tensor是神马?为什么还会Flow?

    Tensor是神马?为什么还会Flow? 互联网爱好者 百家号17-05-2310:03 大数据文摘作品,转载要求见文末 编译 | 邵胖胖,江凡,笪洁琼,Aileen 也许你已经下载了TensorFl ...

  7. Qt_深入了解信号槽(signal&slot)

    转自豆子空间 信号槽机制是Qt编程的基础.通过信号槽,能够使Qt各组件在不知道对方的情形下能够相互通讯.这就将类之间的关系做了最大程度的解耦. 槽函数和普通的C++成员函数没有很大的区别.它们也可以使 ...

  8. yum install 报错[Errno 14] curl#37 - Couldn't open file /mnt/repodata/repomd.xml

    1.然后按照网上的一些修改,先是执行: yum cleam all 然后 yum makecache,问题还是没解决,继续报错. 其实这两条命令就是清空缓存,然后再重新缓存的意思,有时候可能有效. 2 ...

  9. jquery 選擇器

    jquery 選擇器有: 元素選擇器: $("p")選擇所有<p> $("p.intro")選擇所有class=“intro”的<p> ...

  10. python之tkinter使用举例-Button

    tkinter用于编写GUI界面,python3默认已经包含,直接使用. # GUI:tkinter使用举例 import tkinter # 实例化tkinter对象 top = tkinter.T ...