• ACWing 289 环路运输


    Problem

    给定(n)个数(a_1,cdots,a_n),定义(d(i,j) = a_i + a_j + dist(i,j)),其中(dist(i,j) = min(|i - j|,n - |i - j|))
    求一组点对((i_0,j_0)),使得(d(i_0,j_0))最大。
    (n le 1 imes 10^6,a_i le 1 imes 10^7)

    Solution

    Thinking 1

    枚举(i,j)(mathcal{O}(n^2))

    Thinking 2

    发现这个(dist(i,j))其实就是(i)(j)在环上的距离。那么破换成链,可以将(dist)变简洁。

    Thinking 3

    倍长(a),那么问题变成:在新序列中找一组点对((i_0,j_0)),使得(d(i_0,j_0) = a_{i_0} + a_{j_0} + i_0 - j_0(i_0 > j_0,i_0 - j_0 < n / 2))最大。
    考虑对于每一个位置(i),找到最大的(j),发现(a_{i_0} + i_0)是固定的,所以题目变成:枚举(i),找到(a_i + i + left(max_{\j < i,i - j < n / 2}{a_j - j} ight))
    然后这玩意显然可以单调队列啊,(mathcal{O}(n))

    # include <bits/stdc++.h>
    using namespace std;
    # define int long long
    const int N = 2e6 + 5;
    int n;
    int a[N];
    int q[N];
    int ans = 0;
    int head = 1,tail = 0;
    signed main(void)
    {
        scanf("%lld",&n);
        for(int i = 1; i <= n; i++) {scanf("%lld",&a[i]); a[i + n] = a[i];}
        n <<= 1;
        int len = n / 4;
        q[++tail] = 1;
        for(int i = 2; i <= n + len; i++)
        {
            while(head <= tail && i - q[head] > len) ++head;
            ans = max(ans,a[i] + i + a[q[head]] - q[head]);
            while(head <= tail && a[q[tail]] - q[tail] < a[i] - i) --tail;
            q[++tail] = i;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    jsp.图书馆
    jsp第七次作业
    jsp第六次作业
    jsp第四次作业
    JSP第二次作业
    软件测试课堂练习
    Android第六次作业
    Android第五次作业
    Android第四次作业
    Android第三次作业
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/14929023.html
Copyright © 2020-2023  润新知