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;
}