• [NOIp2012]开车旅行


    Description

    Luogu1081

    Solution

    首先可以暴力模拟走的过程即可得70分。
    观察暴力效率低下的原因,其一是向前走的时候比较慢,用倍增的思路优化即可。其二是读入时处理的每个点到每个点的距离,这是不必要的。
    那么如何改进呢?首先,我们发现对于每个点只需要求出最近点和次近点即可,这里可以轻松的想到排序,但是比较难想到的是利用链表来处理“自东向西”这个要求。
    我们可以将每个城市排序后放到链表里,然后自东向西逐个处理,取前驱,前驱的前驱,后缀,后缀的后缀比较即可。之后删除该点,就可以了。

    对答案的处理我写的比较蠢,各种情况分类讨论,应该还有更简洁的方案。

    Code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    const int N = 1e5 + 10;
    
    inline int abs(int x) { return x > 0 ? x : -x; }
    
    struct City {
        int id, h;
        bool operator< (const City &x) const {
            return h < x.h;
        }
    } c[N];
    struct node {
        int id, h;
        bool operator< (const node &x) const {
            return abs(h) == abs(x.h) ? h < x.h : abs(h) < abs(x.h);
        }
    } tmp[5];
    int n, h[N], tot, m;
    int hd[N], nxt[N], pre[N];
    int tar[N][2];
    int dis[N][2][20], to[N][20];
    int as, bs, ans;
    
    inline void addx(int x, int p) {
        tmp[tot].h = c[p].h - h[x];
        tmp[tot].id = c[p].id;
        tot++;
    }
    
    inline void del(int p) {
        pre[nxt[p]] = pre[p];
        nxt[pre[p]] = nxt[p];
    }
    
    void calc_tar(int x, int p) {
        tot = 0;
        memset(tmp, 0, sizeof tmp);
        if (pre[p]) {
            addx(x, pre[p]);
            if (pre[pre[p]]) {
                addx(x, pre[pre[p]]);
            }
        }
        if (nxt[p]) {
            addx(x, nxt[p]);
            if (nxt[nxt[p]]) {
                addx(x, nxt[nxt[p]]);
            }
        }
        std::sort(tmp, tmp+tot);
        if (tmp[0].id) tar[x][0] = tmp[0].id;
        if (tmp[1].id) tar[x][1] = tmp[1].id;
        del(p);
    }
    
    void init() {
        for (int i = 1; i <= n; ++i) {
            to[i][0] = tar[i][1];
            dis[i][0][0] = abs(h[i]-h[to[i][0]]);
            dis[i][1][0] = 0;
        }
        for (int i = 1; i <= n; ++i) {
            to[i][1] = tar[to[i][0]][0];
            dis[i][0][1] = dis[i][0][0];
            dis[i][1][1] = abs(h[to[i][0]] - h[to[i][1]]);
        }
        for (int i = 2; i <= 18; ++i) {
            for (int j = 1; j <= n; ++j) {
                to[j][i] = to[to[j][i-1]][i-1];
                dis[j][0][i] = dis[j][0][i-1] + dis[to[j][i-1]][0][i-1];
                dis[j][1][i] = dis[j][1][i-1] + dis[to[j][i-1]][1][i-1];
            }
        }
    }
    
    inline void work(int st, int mxd) {
        int sa = 0, sb = 0;
        int sst = st;
        for (int i = 18; i >= 0; --i) {
            if (!to[sst][i] || mxd < dis[sst][0][i] + dis[sst][1][i]) continue;
            sa += dis[sst][0][i];
            sb += dis[sst][1][i];
            mxd -= dis[sst][0][i] + dis[sst][1][i];
            sst = to[sst][i];
        }
        if (bs == 0) {
            if (sb == 0) {
                if (h[st] > h[ans]) ans = st;
            } else ans = st;
            as = sa; bs = sb;
            return;
        }
        if (sb == 0) return;
        if ((double)as / bs > (double)sa / sb) {
            as = sa;
            bs = sb;
            ans = st;
        }
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &c[i].h);
            c[i].id = i;
            h[i] = c[i].h;
        }
        std::sort(c+1, c+n+1);
        for (int i = 1; i <= n; ++i) {
            hd[c[i].id] = i;
            pre[i] = i-1;
            nxt[i] = i+1;
        }
        nxt[n] = 0;
        for (int i = 1; i <= n; ++i) {
            calc_tar(i, hd[i]);
        }
        init();
        int x, y;
        scanf("%d", &x);
        for (int i = 1; i <= n; ++i) {
            work(i, x);
        }
        printf("%d
    ", ans);
        scanf("%d", &m);
        for (int i = 1; i <= m; ++i) {
            scanf("%d%d", &x, &y);
            as = bs = 0;
            work(x, y);
            printf("%d %d
    ", as, bs);
        }
        return 0;
    }
    
  • 相关阅读:
    Codeforces Global Round 2
    BZOJ4762 最小集合(动态规划+容斥原理)
    BZOJ4621 Tc605(动态规划)
    Luogu5289 十二省联考2019皮配(动态规划)
    Luogu5290 十二省联考2019春节十二响(贪心+启发式合并)
    Luogu5283 十二省联考2019异或粽子(trie/可持久化trie+堆)
    Luogu5284 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)
    【转】Android的线程使用来更新UI----Thread、Handler、Looper、TimerTask
    android Handler更新UI
    Android 四大组件之Activity生命周期
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/noip201213.html
Copyright © 2020-2023  润新知