当前位置: 代码迷 >> 综合 >> T3 Railway Trip
  详细解决方案

T3 Railway Trip

热度:51   发布时间:2023-10-29 09:12:57.0

来源

http://blog.csdn.net/lych_cys/article/details/78925907

前言

想了一天没想到一道题,于是开始随便翻翻别人的博客
找到了这个题。。感觉还不错,记录一下

题意

给你n个数,每个点向它两边第一个>=它的数连边,m次询问x->y的最短路

做法

考虑倍增f[i][j],g[i][j]表示i走2^j步能到达的最左/最右的点的位置。然后询问先贪心走x,然后贪心走y即可。
正确性显然把。。肯定是走得越远越好啦

CODE:(偷的)

#include<bits/stdc++.h> 
#define N 100009 
using namespace std;  int n,m,a[N],q[N],f[N][17],g[N][17];  
int main(){  scanf("%d%*d%d",&n,&m);  int i,j,l,r,x,y,u,v,ans;  for (i=1; i<=n; i++) scanf("%d",&a[i]);  q[j=1]=1;  for (i=2; i<=n; i++){  for (; j && a[i]>a[q[j]]; j--);  f[i][0]=q[j]; q[++j]=i;  }  q[j=1]=n;  for (i=n-1; i; i--){  for (; j && a[i]>a[q[j]]; j--);  g[i][0]=q[j]; q[++j]=i;  }  f[1][0]=1; g[n][0]=n;  for (j=1; j<=16; j++)  for (i=1; i<=n; i++){  f[i][j]=min(f[f[i][j-1]][j-1],f[g[i][j-1]][j-1]);  g[i][j]=max(g[f[i][j-1]][j-1],g[g[i][j-1]][j-1]);  }  while (m--){  scanf("%d%d",&x,&y); if (x>y) swap(x,y);  l=r=x; ans=0;  for (i=16; i>=0; i--){  u=min(f[l][i],f[r][i]); v=max(g[l][i],g[r][i]);  if (v<y){ l=u; r=v; ans|=1<<i; }  }  x=r; l=r=y;  for (i=16; i>=0; i--){  u=min(f[l][i],f[r][i]); v=max(g[l][i],g[r][i]);  if (u>x){ l=u; r=v; ans+=1<<i; }  }  printf("%d\n",ans);  }  return 0;  
}