• hdu5261单调队列


    题意特难懂,我看了好多遍,最后还是看讨论版里别人的问答,才搞明白题意,真是汗。

    其实题目等价于给n个点,这n个点均匀分布在一个圆上(知道圆半径),点与点之间的路程(弧长)已知,点是有权值的,已知,点与点的距离等于其最短路程(弧长)加上两点的权值,问距离最远的两个点的下标。

    因为是环状,不好处理,所以我在输入的时候就简单处理了一下,使问题变成直线上的等价问题了。做法就是在输入序列后面再加上前半段序列,例如样例5 2 1 10 1 10 10,可以处理成1 10 1 10 10 1 10,这样就只需要顺序处理了,不过最后输成的下标是需要处理的,因为要求的是字典序最小的下标对。

    变成直线后的问题就比较简单了。便于理解的做法是维护一个长度为半圆的队列,当处理i时,把队列里的点和i点比较,更新最值,然后i入队,队列头元素出队。这是n^2的效率,换成单调队列,就能过了。不过,我是用优先队列做的,代码比用单调队列稍复杂一丁点,也是脑子木了,还没打完,金牛就把我代码要了去用单调队列接着打了。先贴上金牛的单调队列的代码,再贴我的,都是1a:

    /*
     * Author : ben
     */
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    #include <string>
    #include <vector>
    #include <deque>
    #include <list>
    #include <functional>
    #include <numeric>
    #include <cctype>
    using namespace std;
    
    #define D(x) 
    
    typedef long long LL;
    const int MAXN = 200000;
    
    int R, N;
    LL m;
    int data[MAXN];
    LL ans;
    int ansi, ansj;
    
    void update(LL a, LL b)
    {
        LL temp = (b - a) * R + data[a] + data[b];
        a %= N - m;
        b %= N - m;
        if (a > b)
            swap(a, b);
        if (temp > ans)
        {
        D(printf("a %lld b %lld
    ", a, b));
            ans = temp;
            ansi = a;
            ansj = b;
            return;
        }
        if (temp < ans)
            return;
        if (ans == 40)
        if (ansi > a || (ansi == a && ansj > b))
        {
            ansi = a;
            ansj = b;
            return;
        }
    }
    
    LL work() {
    
        deque<LL> q;
        q.push_back(0);
        long long cur_pos = 0;
        long long ret = 0;
        for (int i = 1; i < N; i++)
        {
            cur_pos += R;
            while (!q.empty() && q.front() < i - m)
                q.pop_front();
            update(q.front(), i);
            while (!q.empty() && (i - q.back()) * R + data[q.back()] < data[i])
                q.pop_back();
            q.push_back(i);
        }
        return ret;
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        for (int t = 1; t <= T; t++) {
            scanf("%d %d", &N, &R);
            for (int i = 0; i < N; i++) {
                scanf("%d", &data[i]);
            }
            m = N / 2;
            for (int i = 0; i < m; i++) {
                data[i + N] = data[i];
            }
            N += m;
            ans = 0;
            work();
            printf("Case #%d
    %d %d
    ", t, ansi + 1, ansj + 1);
        }
        return 0;
    }

    下面是我的优先队列的:

    /*
     * Author    : ben
     */
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    #include <string>
    #include <vector>
    #include <deque>
    #include <list>
    #include <functional>
    #include <numeric>
    #include <cctype>
    using namespace std;
    typedef long long LL;
    const int MAXN = 200000;
    typedef struct Mont {
        int height;
        int index;
        LL value;
        Mont(int ii = 0, int hh = 0, LL vv = 0) {
            height = hh;
            index = ii;
            value = vv;
        }
    } Mont;
    bool inline operator<(const Mont& m1, const Mont& m2) {
        return m1.value < m2.value;
    }
    LL R;
    int N, m;
    int data[MAXN];
    LL ans;
    int ansi, ansj;
    
    inline void treat(int &i, int &j) {
        if (i >= N - m) {
            i = i % (N - m);
        }
        if (j >= N - m) {
            j = j % (N - m);
        }
        if (i > j) {
            int t = i;
            i = j;
            j = t;
        }
    }
    
    void work() {
        priority_queue<Mont> mont;
        mont.push(Mont(0, data[0], data[0]));
        for (int i = 1; i < N; i++) {
            while (mont.top().index < (i - m)) {
                mont.pop();
            }
            Mont topm = mont.top();
            LL tans = (i - topm.index) * R + data[i] + data[topm.index];
            if (tans > ans) {
                ans = tans;
                ansi = topm.index;
                ansj = i;
                treat(ansi, ansj);
            } else if(tans == ans) {
                int x = topm.index;
                int y = i;
                treat(x, y);
                if (x < ansi || (x == ansi && y < ansj)) {
                    ansi = x;
                    ansj = y;
                }
            }
            mont.push(Mont(i, data[i], data[i] - i * R));
        }
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        for (int t = 1; t <= T; t++) {
            scanf("%d %lld", &N, &R);
            for (int i = 0; i < N; i++) {
                scanf("%d", &data[i]);
            }
            m = N / 2;
            for (int i = 0; i < m; i++) {
                data[i + N] = data[i];
            }
            N += m;
            ans = 0;
            work();
            printf("Case #%d:
    %d %d
    ", t, ansi + 1, ansj + 1);
        }
        return 0;
    }
  • 相关阅读:
    Java :BufferedWriter类和BufferedReader类的构造方法、主要方法
    多线程:四大线程池详解
    多线程:head first Thread.join()
    多线程: 多线程中断机制
    多线程:深入Thread.sleep
    多线程:线程池原理
    java:java构造器和java方法的区别
    java: Java中this和super的用法总结
    postman: 用于网页调试和发送Http请求的chrome插件
    json:JSONObject包的具体使用(JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包)
  • 原文地址:https://www.cnblogs.com/moonbay/p/4557451.html
Copyright © 2020-2023  润新知