zoukankan      html  css  js  c++  java
  • Codeforces 631E Product Sum 斜率优化

    我们先把问题分成两部分, 一部分是把元素往前移, 另一部分是把元素往后移。对于一个 i 后的一个位置, 我们考虑前面哪个移到这里来最优。

    我们设最优值为val,   val = max(a[ j ] * (i - j) - (sum[ i ] - sum[ j ]) 我们能发现这个能转换成斜率优化的形式如果 j 比 k 更优且 j > k 我们能得到, 

    ((j * a[ j ] - sum[ j ])  - (k * a[ k ] - sum[ k ]))  < i *  (a[ j ] - a[ k ]) ,这时候我们发现(a[ j ] - a[ k ])的符号不知道, 因为 a 不是单调的。 

    是我们能发现有用的 a 一定是单调递增的, 我们考虑相邻的情况,如果前面的a大, 那么它和它后一个交换肯定变优。 这样就能斜率优化啦,

    反过来的情况也是一样的。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ull unsigned long long
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    int n, head = 1, rear, que[N];
    LL a[N], sum[N], ans;
    
    inline double calc(int k, int j) {
        return (((double)j * a[j] - sum[j]) - ((double)k * a[k] - sum[k])) / (a[j] - a[k]);
    }
    
    int main() {
    //    freopen("text.in", "r", stdin);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
            ans += i * a[i];
            sum[i] = sum[i - 1] + a[i];
        }
        LL tmp = ans;
        for(int i = 1; i <= n; i++) {
            while(rear - head + 1 >= 2 && calc(que[head], que[head + 1]) <= i) head++;
            if(head <= rear) {
                int who = que[head];
                ans = max(ans, tmp + (i - who) * a[who] - sum[i] + sum[who]);
            }
            if(head > rear || (head <= rear && a[i] > a[que[rear]])) {
                while(rear - head + 1 >= 2 && calc(que[rear - 1], que[rear]) > calc(que[rear], i)) rear--;
                que[++rear] = i;
            }
        }
    
        rear = 0; head = 1;
        reverse(a + 1, a + 1 + n);
        for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i];
        for(int i = 1; i <= n; i++) {
            while(rear - head + 1 >= 2 && calc(que[head], que[head + 1]) <= i) head++;
            if(head <= rear) {
                int who = que[head];
                ans = max(ans, tmp + sum[i] - sum[who] - (i - who) * a[who]);
            }
            if(head > rear || (head <= rear && a[i] < a[que[rear]])) {
                while(rear - head + 1 >= 2 && calc(que[rear - 1], que[rear]) > calc(que[rear], i)) rear--;
                que[++rear] = i;
            }
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    类实现接口(Example5_11)
    PyTorch之Checkpoint机制解析
    PyTorch之BN核心参数详解
    PyTorch之分布式操作Barrier
    PyTorch之对类别张量进行onehot编码
    PyTorch之具体显存占用分析
    Pytorch之SpatialShiftOperation的5种实现策略
    无密码远程桌面设置
    人生三个境界
    研华工控机设置上电自启动
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10471099.html
Copyright © 2011-2022 走看看