• [BZOJ4709][JSOI2011]柠檬[决策单调性优化]


    有太多题解在瞎写,发这个主要是提醒一下不要被傻逼们写的东西误导

    好几次想要把这个题想明白,但那些所谓的“题解”让我浪费了许多天时间

    QQ截图20181108102107.png
    QQ截图20181108103057.png

    二分的是s[i],单调栈里的元素比较关键字也是s[i],而不是位置,要是强行把s[i]说成时间,我仏了

    随便看看其他人写的,不管正确性,不管是否理解,把代码和文字抄过去,就会产生这种“题解”,网络垃圾

    问某人,说“不懂啊,照其他题解抄的”,你就继续制造一篇垃圾题解?

    我看这篇才明白的

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 6;
    int a[MAXN], cnt[MAXN], s[MAXN], n, m;
    long long f[MAXN];
    vector<int>q[MAXN];
    #define mid ((l+r)>>1)
    long long Get(int x, int y) {return f[x - 1] + 1ll * a[x] * y * y;}
    inline int Get_s(int x, int y) {//二分出x比y优的最小的s
      int l = 1, r = n, ans = 1e9;//x永远不会比y优的话 ans = inf
      while (l <= r) {
        if (Get(x, mid - s[x] + 1) >= Get(y, mid - s[y] + 1)) ans = mid, r = mid - 1;
        else l = mid + 1;
      }
      return ans;
    }
    
    
    int main() {
      scanf("%d", &n);
      for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), s[i] = ++cnt[a[i]];
      for (int i = 1; i <= n; ++i) {
        vector<int> &v = q[a[i]];
        while (v.size() >= 2 && Get_s(*----v.end(), *--v.end()) <= Get_s(*--v.end(), i)) v.pop_back();
        //栈顶下面的元素比栈顶优的s <= 栈顶比 i 优的 s
        //当栈顶比i优的时候 第二个元素一定比栈顶优 所以栈顶没有用 可以弹出
        v.push_back(i);
        while (v.size() >= 2 && Get_s(*----v.end(), *--v.end()) <= s[i]) v.pop_back();
        //如果第二个元素比栈顶优的最小s<=s[i] 就可以弹出栈顶
        f[i] = Get(*--v.end(), s[i] - s[*--v.end()] + 1);
      }
      cout << f[n];
      return 0;
    }
    
    /*
    5
    2 2 1 2 3
    dp[1] = 2 
    dp[2] = 8
    Get_s(1, 2) = 1 <= s[2](2)
    s = 1的时候 1就会比2优 -> pop掉2
    
    */
    
  • 相关阅读:
    C++11 学习总结
    平衡二叉树 (AVL) 笔记
    拼图模板
    2013.9.12
    2013.9.11
    2013.9.10
    2013.9.9
    下载网站
    ubuntu 安装codeblocks
    12个球称3次找坏球的完美解答
  • 原文地址:https://www.cnblogs.com/storz/p/9983205.html
Copyright © 2020-2023  润新知