• luogu P1081 开车旅行


    传送门

    这题的暴力做法显然是照题意模拟,从每个点出发暴力跳.而这个暴跳显然是可以倍增优化的,就是预处理出从每个点,(一开始是A)往后跳(2^k)步,能到哪里,以及(A)(B)的路程,然后暴力跳的时候倍增跳即可

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    #define eps (1e-5)
    
    using namespace std;
    const int N=100000+10;
    il LL rd()
    {
      LL x=0,w=1;char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    int n,nn,nt[N][2],m,x;
    LL jp[N][20][3],h[N];
    struct node
    {
      int x;
      node(){}
      node(int nwx){x=nwx;}
      bool operator < (const node &bb) const {return h[x]<h[bb.x];}
    };
    struct ppx
    {
      LL a,b,i;
      ppx(){}
      ppx(LL nwa,LL nwb,LL nwi){a=nwa,b=nwb,i=nwi;}
      bool operator < (const ppx &bb) const {return h[i]!=h[bb.i]?(b==0&&bb.b>0?true:a*bb.b>b*bb.a):h[i]<h[bb.i];}
    };
    set<node> s;
    priority_queue<ppx> q;
    
    int main()
    {
      n=rd();nn=log2(n);
      for(int i=1;i<=n;i++) h[i]=rd();
      h[n+1]=-2e9-7,h[n+2]=-2e9-8,h[n+3]=2e9+7,h[n+4]=2e9+8;
      s.insert(node(n+1)),s.insert(node(n+2)),s.insert(node(n+3)),s.insert(node(n+4));
      for(int i=n;i>=1;i--) //预处理每个点往后最近的和次近的位置
        {
          s.insert(node(i));
          set<node>::iterator it=s.lower_bound(node(i));
          int frt,nxt;
          ++it,nxt=node(*it).x,--it,--it,frt=node(*it).x,++it;
          if(h[nxt]-h[i]<h[i]-h[frt])
            {
              nt[i][1]=nxt;
              ++it,++it,nxt=(*it).x;
              nt[i][0]=h[nxt]-h[i]<h[i]-h[frt]?nxt:frt;
            }
          else 
            {
              nt[i][1]=frt;
              --it,--it,frt=(*it).x;
              nt[i][0]=h[nxt]-h[i]<h[i]-h[frt]?nxt:frt;
            }
        }
      for(int i=1;i<=n;i++)
        jp[i][0][0]=abs(h[nt[i][0]]-h[i]),jp[i][0][2]=nt[i][0],jp[i][1][0]=abs(h[nt[i][0]]-h[i]),jp[i][1][1]=abs(h[nt[nt[i][0]][1]]-h[nt[i][0]]),jp[i][1][2]=nt[nt[i][0]][1];
      for(int j=2;j<=nn;j++)
        for(int i=1;i<=n;i++)
          jp[i][j][0]=jp[i][j-1][0]+jp[jp[i][j-1][2]][j-1][0],jp[i][j][1]=jp[i][j-1][1]+jp[jp[i][j-1][2]][j-1][1],jp[i][j][2]=jp[jp[i][j-1][2]][j-1][2];
      x=rd();
      for(int i=1;i<=n;i++)
        {
          int nw=i,las=nn;
          LL xx=x,nwa=0,nwb=0;
          for(int j=nn;j>=0;j--)
            if(jp[nw][j][2]<=n&&xx-(jp[nw][j][0]+jp[nw][j][1])>=0) las=j,xx-=jp[nw][j][0]+jp[nw][j][1],nwa+=jp[nw][j][0],nwb+=jp[nw][j][1],nw=jp[nw][j][2];
          if(!las&&xx-abs(h[nt[nw][1]]-h[nw])>=0) nwb+=abs(h[nt[nw][1]]-h[nw]);
          q.push(ppx(nwa,nwb,i));
        }
      printf("%lld
    ",q.top().i);
      m=rd();
      while(m--)
        {
          int nw=rd(),las=nn;
          LL xx=rd(),nwa=0,nwb=0;
          for(int j=nn;j>=0;j--)
            if(jp[nw][j][2]<=n&&xx-(jp[nw][j][0]+jp[nw][j][1])>=0) las=j,xx-=jp[nw][j][0]+jp[nw][j][1],nwa+=jp[nw][j][0],nwb+=jp[nw][j][1],nw=jp[nw][j][2];
          if(!las&&xx-abs(h[nt[nw][1]]-h[nw])>=0) nwb+=abs(h[nt[nw][1]]-h[nw]);
          printf("%lld %lld
    ",nwa,nwb);
        }
      return 0; //很丑是不是(逃
    }
    
    
    
  • 相关阅读:
    CCF-CSP-201803-3 URL映射
    CCF-CSP-201803-2 碰撞的小球
    CCF-CSP-201803-1 跳一跳
    SSH协议基础学习
    关于Kali-linux2019.4系统安装后乱码问题
    git版本控制工具学习--修改分支名字
    Git版本控制工具操作学习系列-克隆项目
    python函数int()转型报错
    Centos关机与重启命令收集学习
    Git commit 提交规范 & 规范校验
  • 原文地址:https://www.cnblogs.com/smyjr/p/9920663.html
Copyright © 2020-2023  润新知