https://vjudge.net/contest/351286#problem/A
题意:1~n位置有不同高度的柱子,一直飞鼠只能从一个柱子飞到高度严格比它小的柱子;
给定n个柱子的高度 ,m次询问:1.从一个柱子最多能飞到多少个柱子上,2.从一个柱子到另一个柱子最多能飞多少次
RMQ查询区间最大值
对于第一种询问dfs求最多路径,把相同高的柱子视为分隔点,相同高的柱子在分隔点之间往下dfs,求出最长路径
对于第二种询问,给柱子分层,最高的为第一层,在它左边次低的和在他右边次低的为第二层,对于两个柱子之间,若有你最高的柱子还高的柱子,则不可达,路径长度为0,否则路径长度为两个柱子的层数之差;
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+9;
int fa[maxn][20],deep[maxn],ans[maxn],h[maxn],n;
int Max(int l,int r)
{
return h[l]>=h[r]?l:r;
}
void rmq()
{
for(int i = 1; i<=n; i++)
{
fa[i][0] = i;
}
for(int j = 1; (1<<j)<=n; j++)
{
for(int i = 1; i+(1<<(j-1))<=n; i++)
{
fa[i][j] = Max(fa[i][j-1],fa[i+(1<<(j-1))][j-1]);
}
}
}
int get_max(int l,int r)
{
int k = (int)(log(r-l+1)/log(2.0));
return Max(fa[l][k],fa[r+1-(1<<k)][k]);
}
int dfs(int l,int r,int lev)
{
if(l>r)
return -1;
int now = get_max(l,r);
deep[now] = lev;
ans[now] = dfs(l,now-1,lev+1)+1;
int res = ans[now];
while(now<r)//对相同高度的柱子分层
{
int next = get_max(now+1,r);
if(h[now]!=h[next])
break;
deep[next] = lev;
int tmp = dfs(now+1,next-1,lev+1)+1;
ans[now] = max(ans[now],tmp);
res = max(res,tmp);
ans[next] = tmp;
now = next;
}
ans[now] = max(ans[now],dfs(now+1,r,lev+1)+1);
res = max(ans[now],res);
return res;
}
int main()
{
int i,j,m,l,r;
scanf("%d %d",&n,&m);
for(i = 1; i<=n; i++)
{
scanf("%d",&h[i]);
}
rmq();
dfs(1,n,1);
while(m--)
{
scanf("%d %d",&l,&r);
if(r==0)
{
printf("%d\n",ans[l]);
}
else
{
if(l==r)
printf("0\n");
else
{
if(h[l]<h[r])
swap(l,r);
int p;
if(l<r)
p = get_max(l+1,r);
else
p = get_max(r,l-1);
if(h[p]>=h[l])
printf("0\n");
else
printf("%d\n",deep[r]-deep[l]);
}
}
}
return 0;
}