[rmq] Jzoj P5863 移动光标
代码
- 一般的情况,当然移动的次数就是|x1-x2|+|y1-y2|
- 那么考虑x1~x2中每行的长度的最小值,是小于y2的
- 这样就不能直接走了,考虑从y1走到m,再走到y2
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 using namespace std; 5 int n,q,x1,x2,y,y2,ans,f[100010][20]; 6 int getmin(int l,int r) 7 { 8 int len=r-l+1,k=trunc(log(len+0.5)/log(2)); 9 return min(f[l][k],f[l+len-(1<<k)][k]); 10 } 11 int main() 12 { 13 freopen("cusor.in","r",stdin); 14 freopen("cusor.out","w",stdout); 15 scanf("%d",&n); 16 for (int i=1;i<=n;i++) scanf("%d",&f[i][0]); 17 for (int j=1;j<20;j++) 18 for (int i=1;i<=n;i++) 19 { 20 f[i][j]=f[i][j-1]; 21 if (i+(1<<j-1)<=n) f[i][j]=min(f[i][j],f[i+(1<<j-1)][j-1]); 22 } 23 scanf("%d",&q); 24 for (int i=1;i<=q;i++) 25 { 26 scanf("%d%d%d%d",&x1,&y,&x2,&y2); 27 if (x1>x2) swap(x1,x2),swap(y,y2); 28 int mn=getmin(x1,x2),ans=0; 29 if (y>mn) ans+=y-mn,y=mn; 30 if (y2>mn) ans+=y2-mn,y2=mn; 31 ans+=abs(y-y2)+(x2-x1); 32 printf("%d\n",ans); 33 } 34 }