zoukankan      html  css  js  c++  java
  • [NOIP 2012] 开车旅行

    题意:

    传送门

    题解:

    set+倍增。

    这题是一个高效模拟题,所以一般都要用一些比较高效的算法,小A和小B的路线都是固定的,所以很容易想到倍增来高效查询路线。

    那么设:
    g[i][j]表示从i开始往后(2^j)轮,车开到的城市。
    f[i][j][0]表示从i开始往后(2^j)轮,小A开车的路程。
    f[i][j][1]表示从i开始往后(2^j)轮,小B开车的路线。

    首先预处理出走一轮的路线,这个可以用set来实现。

    然后倍增转移。

    对于第一问,直接暴枚每个点为起点,比较一下即可。

    对于第二问,同理直接查询。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<set>
    #define ll long long
    #define N 100010
    using namespace std;
    
    int h[N],g[N][22],f[N][22][2],dis[N][2],to[N][2];
    
    set<int> q;
    map<int,int> mp;
    
    int gi() {
      int x=0,o=1; char ch=getchar();
      while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
      if(ch=='-') o=-1,ch=getchar();
      while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
      return o*x;
    }
    
    void update(int x, int y) {
      int a=mp[x],b=mp[y],d=abs(x-y);
      if(!to[a][0] || d<dis[a][0] || (d==dis[a][0] && y<h[to[a][0]])) {
        to[a][1]=to[a][0],dis[a][1]=dis[a][0];
        to[a][0]=b,dis[a][0]=d;
      }
      else if(!to[a][1] || d<dis[a][1] || (d==dis[a][1] && y<h[to[a][0]])) {
        to[a][1]=b,dis[a][1]=d;
      }
    }
    
    void query(int x, int len, ll &a, ll &b) {
      for(int i=20; i>=0; i--) {
        if(g[x][i] && f[x][i][0]+f[x][i][1]<=len) {
          a+=f[x][i][0];
          b+=f[x][i][1];
          len-=f[x][i][0]+f[x][i][1];
          x=g[x][i];
        }
      }
      if(to[x][1] && dis[x][1]<=len) a+=dis[x][1]; 
    }
    
    int main() {
      int n=gi(),m,x,len,ans;
      ll ansa=0,ansb=0,a,b;
      for(int i=1; i<=n; i++) mp[h[i]=gi()]=i;
      for(int i=n; i>=1; i--) {
        q.insert(h[i]);
        set<int>::iterator it;
        it=q.find(h[i]);
        if(it!=q.begin()) {
          it--;
          update(h[i],*it);
          if(it!=q.begin()) {it--,update(h[i],*it),it++;}
          it++;
        }
        if((++it)!=q.end()) {
          update(h[i],*it);
          if((++it)!=q.end()) update(h[i],*it);
        }
      }
      for(int i=1; i<=n; i++) {
        g[i][0]=to[to[i][1]][0];
        f[i][0][0]=dis[i][1];
        f[i][0][1]=dis[to[i][1]][0];
      }
      for(int j=1; j<=20; j++)
        for(int i=1; i<=n; i++) {
          g[i][j]=g[g[i][j-1]][j-1];
          f[i][j][0]=f[i][j-1][0]+f[g[i][j-1]][j-1][0];
          f[i][j][1]=f[i][j-1][1]+f[g[i][j-1]][j-1][1];
        }
      len=gi();
      for(int i=1; i<=n; i++) {
        a=0,b=0;
        query(i,len,a,b);
        if(b && (!ansb || a*ansb<b*ansa || (a*ansb==b*ansa && h[i]>h[ans]))) ans=i,ansa=a,ansb=b;
      }
      printf("%d
    ", ans);
      m=gi();
      while(m--) {
        x=gi(),len=gi(),a=0,b=0;
        query(x,len,a,b);
        printf("%lld %lld
    ", a,b);
      }
      return 0;
    }
    
  • 相关阅读:
    hdu 5119 Happy Matt Friends
    hdu 5128 The E-pang Palace
    hdu 5131 Song Jiang's rank list
    hdu 5135 Little Zu Chongzhi's Triangles
    hdu 5137 How Many Maos Does the Guanxi Worth
    hdu 5122 K.Bro Sorting
    Human Gene Functions
    Palindrome(最长公共子序列)
    A Simple problem
    Alignment ( 最长上升(下降)子序列 )
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7808983.html
Copyright © 2011-2022 走看看