zoukankan      html  css  js  c++  java
  • C2. Skyscrapers (hard version)

    思路:

    显然满足题意的一定是一个单峰序列,于是可以考虑第i个当最高点的时候,左边的最大总和,而这个是可以递推的,因为当m[i]>=m[i-1]的时候第i个可以直接取m[i]加上去,而当m[i] < m[i-1]的时候,要把之前所有大于m[i]的都变成m[i],而之前的部分是单增的,于是可以开个单调栈来维护,复杂度O(n),同理右边的最大总和也可以这么算。

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
    #include <bitset>
    #include <cmath>
    #include <sstream>
    
    #define LL long long
    #define INF 0x3f3f3f3f
    #define ls nod<<1
    #define rs (nod<<1)+1
    
    const double eps = 1e-10;
    const int maxn = 5e5 + 10;;
    const LL mod = 1e9 + 7;
    
    int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
    using namespace std;
    
    struct node {
        int val,cnt;
    }nd[maxn];
    
    int a[maxn],b[maxn];
    LL f[maxn],g[maxn];
    int main() {
        int n;
        cin >> n;
        for (int i = 1;i <= n;i++)
            cin >> a[i];
        int cnt = 0;
        for (int i = 1;i <= n;i++) {
            if (a[i] >= a[i-1]) {
                nd[++cnt].val = a[i];
                nd[cnt].cnt = 1;
                f[i] = f[i-1] + a[i];
            }
            else {
                LL sum = 0;
                int num = 0;
                while (cnt >= 1 && nd[cnt].val >= a[i]) {
                    sum += nd[cnt].val * 1ll * nd[cnt].cnt;
                    num += nd[cnt].cnt;
                    cnt--;
                }
                nd[++cnt].val = a[i];
                nd[cnt].cnt = num+1;
                f[i] = f[i-1] - sum + 1ll*nd[cnt].val*nd[cnt].cnt;
            }
        }
        cnt = 0;
        for (int i = n;i >= 1;i--) {
            if (a[i] >= a[i+1]) {
                nd[++cnt].val = a[i];
                nd[cnt].cnt = 1;
                g[i] = g[i+1] + a[i];
            }
            else {
                LL sum = 0;
                int num = 0;
                while (cnt >= 1 && nd[cnt].val >= a[i]) {
                    sum += nd[cnt].val * 1ll * nd[cnt].cnt;
                    num += nd[cnt].cnt;
                    cnt--;
                }
                nd[++cnt].val = a[i];
                nd[cnt].cnt = num+1;
                g[i] = g[i+1] - sum + 1ll*nd[cnt].val*nd[cnt].cnt;
            }
        }
        int id = 1;
        for (int i = 2;i <= n;i++) {
            if (f[i] + g[i] - a[i] > f[id] + g[id] - a[id]) {
                id = i;
            }
        }
        b[id] = a[id];
        for (int i = id-1;i >= 1;i--) {
            b[i] = min(b[i+1],a[i]);
        }
        for (int i = id+1;i <= n;i++) {
            b[i] = min(b[i-1],a[i]);
        }
        for (int i = 1;i <= n;i++) {
            cout << b[i] << " ";
        }
        cout << endl;
        return 0;
    }
  • 相关阅读:
    "科林明伦杯"哈理工第九届——分布式服务(概率期望+思维)
    Nim游戏——简单博弈论
    acwing 1252搭配购买(并查集 + 01背包 )
    [LeetCode] 67. Add Binary
    [LeetCode] 415. Add Strings
    [LeetCode] 43. Multiply Strings
    [LeetCode] 412. Fizz Buzz
    [LeetCode] 201. Bitwise AND of Numbers Range
    [LeetCode] 389. Find the Difference
    [LeetCode] 326. Power of Three + 342. Power of Four
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12392361.html
Copyright © 2011-2022 走看看