zoukankan      html  css  js  c++  java
  • 【NOIP2012提高组】开车旅行 倍增

    题目分析

    朴素的做法就是预处理下一个目的地,然后跑模拟,超时。

    本题最重要的考点是倍增优化。设$fa[i][j]$表示a从i出发行驶$2^j$“次”后行驶的路程,$fb[i][j]$表示从i出发行驶$2^j$“次”后行驶的路程,注意这里的"次",a、b交替行驶。$f[i][j]$表示从i出发a、b交替$2^j$“次”后行驶到的城市编号。

    显然有$fa[i][j] = fa[i][j - 1] + fa[f[i][j - 1]][j - 1], fb = fb[i][j - 1] + fb[f[i][j - 1]], f[i][j] = ff[i][j - 1]][j - 1]$。只需要用set求出前驱后继和次前驱后继,就能正确预处理出来。最后在路径上跑倍增就行。

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<set>
    using namespace std;
    
    const int N = 1e5 + 5;
    int n, x0, m, nxta[N], nxtb[N], f[N][30];
    typedef long long ll;
    ll fa[N][30], fb[N][30];
    struct node2{
        int h, pos;
        inline bool operator < (const node2 &b) const{
            return h < b.h;
        }
    }data[N];
    struct node{
        int pos, dis;
        inline bool operator < (const node &b) const{
            if(dis != b.dis) return dis < b.dis;
            return data[pos].h < data[b.pos].h;
        }
    }t[10];
    set<node2> S;
    
    inline int read(){
        int i = 0, f = 1; char ch = getchar();
        for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
        if(ch == '-') f = -1, ch = getchar();
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            i = (i << 3) + (i << 1) + (ch - '0');
        return i * f;
    }
    
    inline void wr(ll x){
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) wr(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline void Find(int x){
        int    cnt = 0;
        set<node2>::iterator it = S.find(data[x]);
        if(it != S.begin()){
            --it;
            t[++cnt] = (node){it->pos, abs(data[x].h - it->h)};
    
            if(it != S.begin())        {
                --it;
                t[++cnt] = (node){it->pos, abs(data[x].h - it->h)};
                ++it;
            }
            ++it;
        }
        if((++it) != S.end()){
            t[++cnt] = (node){it->pos, abs(it->h - data[x].h)};
            if((++it) != S.end()){
                t[++cnt] = (node){it->pos, abs(it->h - data[x].h)};
                --it;
            }
            --it;
        }
        sort(t + 1, t + cnt + 1);
        nxtb[x] = t[1].pos;
        if(cnt > 1)
            nxta[x] = t[2].pos;
    }
    
    inline void init(){
        for(int i = 1; i <= n; i++){
            int na = nxta[i], nb = nxtb[na];
            fa[i][0] = na ? abs(data[na].h - data[i].h) : 0;
            fb[i][0] = nb ? abs(data[nb].h - data[na].h) : 0;
            f[i][0] = nb;
        }
        for(int j = 1; j <= 20; j++)
            for(int i = 1; i <= n; i++){
                f[i][j] = f[f[i][j - 1]][j - 1];
                fa[i][j] = fa[i][j - 1] + fa[f[i][j - 1]][j - 1];
                fb[i][j] = fb[i][j - 1] + fb[f[i][j - 1]][j - 1];
            }
    }
    
    inline void query(int s, ll x, ll &na, ll &nb){
        for(int i = 20; i >= 0; i--)
            if(f[s][i] && fa[s][i] + fb[s][i] <= x){
                na += fa[s][i], nb += fb[s][i];
                x -= fa[s][i] + fb[s][i];
                s = f[s][i];
            }
        int posa = nxta[s], d = abs(data[s].h - data[posa].h); 
        if(posa &&  d <= x) na += d;
    }
    
    int main(){
        n = read();
        for(int i = 1; i <= n; i++) data[i] = (node2){read(), i};
        for(int i = n; i >= 1; i--){
            S.insert(data[i]);
            if(i ^ n) Find(i);
        }
        init();
        x0 = read();
        int ans = 0;
        ll ansa = 0, ansb = 0;
        for(int i = 1; i <= n; i++){
            ll na = 0, nb = 0;
            query(i, x0, na, nb);
            if(!ans || ansa * nb > ansb * na) ans = i, ansa = na, ansb = nb;
        }
        wr(ans), putchar('
    ');
        m = read();
        for(int i = 1; i <= m; i++){
            ll na = 0, nb = 0;
            int st = read(), x = read();
            query(st, x, na, nb);
            wr(na), putchar(' '), wr(nb), putchar('
    ');
        }
        return 0;
    }
  • 相关阅读:
    Spring 事务不回滚
    Druid详细配置信息
    Servlet和JSP规范及版本对应关系
    CDN(内容分发网络)技术原理
    开发者需要了解的WebKit
    浏览器的渲染原理简介
    在浏览器中输入Google.com并且按下回车之后发生了什么?
    为什么说DOM操作很慢
    亿级Web系统搭建——单机到分布式集群
    linux下用rinetd做端口转发
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7429545.html
Copyright © 2011-2022 走看看