zoukankan      html  css  js  c++  java
  • loj2395 [JOISC 2017 Day 2]火车旅行

    传送门

    分析

    我们知道无论往左走还是往右走一定都是往不低于这个点的地方走

    于是我们可以考虑用倍增来维护一个点向左和向右走$2^i$最远分别能走到哪里

    我们可以先用单调栈求出直走一步的情况,之后再处理倍增数组

    值得注意的是有可能一直往左走不是最优情况,而先向右再想左会使答案更优

    于是le[x][i]=min(le[le[x][i-1]][i-1],le[ri[x][i-1]][i-1])

    向右的情况同理

    于是我们进一步考虑如何通过倍增数组得到答案、

    我们先从左面往右走,只要走$2^i$不会超过右节点则就让它走这么多步

    一直走到不能再走之后再从右往左走

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    const int LOG = 18;
    int a[100100],le[100100][LOG+3],ri[100100][LOG+3],st[100100],top;
    int main(){
        int n,m,i,j,k;
        scanf("%d%d%d",&n,&k,&m);
        for(i=1;i<=n;i++)scanf("%d",&a[i]);
        top=0;
        st[0]=1;
        for(i=1;i<=n;i++){
          while(top&&a[st[top]]<a[i])top--;
          le[i][0]=st[top];
          st[++top]=i;
        }
        top=0;
        st[0]=n;
        for(i=n;i>0;i--){
          while(top&&a[st[top]]<a[i])top--;
          ri[i][0]=st[top];
          st[++top]=i;
        }
        for(i=1;i<=LOG;i++)
          for(j=1;j<=n;j++){
            le[j][i]=min(le[le[j][i-1]][i-1],le[ri[j][i-1]][i-1]);
            ri[j][i]=max(ri[ri[j][i-1]][i-1],ri[le[j][i-1]][i-1]);
          }
        while(m--){
          int x,y,Ans=0,L,R,tl,tr;
          scanf("%d%d",&x,&y);
          if(x>y)swap(x,y);
          L=R=x;
          for(i=LOG;i>=0;i--){
              tl=min(le[L][i],le[R][i]);
              tr=max(ri[L][i],ri[R][i]);
              if(tr<y){
                L=tl,R=tr;
                Ans+=(1<<i);
              }
          }
          x=R;
          L=R=y;
          for(i=LOG;i>=0;i--){
              tl=min(le[L][i],le[R][i]);
              tr=max(ri[L][i],ri[R][i]);
              if(tl>x){
                L=tl,R=tr;
                Ans+=(1<<i);
              }
          }
          printf("%d
    ",Ans);
        }
        return 0;
    }
  • 相关阅读:
    Linux 常用命令
    公钥,私钥和数字签名
    MySQL中的datetime与timestamp比较
    SQL开发技巧
    socket心跳包机制
    vue 路由回退,实现刷新原页面数据
    HTTP1.0、HTTP1.1 和 HTTP2.0 的区别
    Xshell常用命令
    学习Dart flutter --1
    学习JavaScript数据结构与算法(第2版)--01
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9913163.html
Copyright © 2011-2022 走看看