• Luogu 1484 种树


    Luogu 1792 算是双倍经验。

    我们考虑对于一个点,我们要么选它,要么选它周围的两个点。

    所以我们考虑用一个堆来维护,每次从堆顶取出最大值之后我们把它的权值记为:它左边的权值加上它右边的权值减去它自己的权值。即$a_{pos} = a_{l(pos)} + a_{r(pos)} - a_{pos}$。然后把它丢到堆里去。

    这样子如果下次取出来这个值就相当于不选原来选过的那个点,而改选它旁边的两个点,而这样选的总的点数也是一样的,这个过程也可以扩展到一个区间,所以这样子可以求出最优解。

    对于那些取出来的点的两边的点,我们下次在取出来的时候不应该再计算贡献,所以记一个$vis$。

    这个“左边的点”和“右边的点”可以用链表维护。

    注意到本题中不一定选满$k$个,所以当取出来的堆顶权值为负的时候直接$break$掉,而在Luogu1792中一定要选满$k$个。

    时间复杂度$O(klogn)$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    typedef long long ll;
    
    const int N = 5e5 + 5;
    
    int n, K, nxt[N], pre[N];
    ll a[N];
    bool vis[N];
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    struct Node {
        ll val; int pos;
        
        Node(ll v = 0, int p = 0) {val = v, pos = p;}
        
        friend bool operator < (const Node &x, const Node &y) {
            return x.val < y.val;
        }
        
    };
    priority_queue <Node> Q;
    
    inline void del(int p) {
        nxt[pre[p]] = nxt[p];
        pre[nxt[p]] = pre[p];
        vis[p] = 1;
    }
    
    int main() {
        read(n), read(K);
        for(int i = 1; i <= n; i++) {
            read(a[i]);
            nxt[i] = i + 1, pre[i] = i - 1;
            Q.push(Node(a[i], i));
        }
        
        ll ans = 0LL;
        for(; K--; ) {
            for(; vis[Q.top().pos]; Q.pop());
            Node out = Q.top(); Q.pop();
            if(out.val < 0) break;
            int x = pre[out.pos], y = nxt[out.pos];
            ans += out.val;
            Q.push(Node(a[out.pos] = a[x] + a[y] - out.val, out.pos));
            del(x), del(y);
        }
        
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    再深一点:如何给女朋友解释什么是微服务?
    图文详解:内存总是不够,我靠HBase说服了Leader为新项目保驾护航
    Java多态总结
    猴子吃桃问题(南阳ACM324)
    杭电acm-2007平方和立方和
    出现错误,修改后的
    今天的第一个程序-南阳acm输入三个数排序
    Azure Blob上传和下载
    用Aspose.Cells把Excel文件转成PDF
    Ionic IOS打包第二节
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9617800.html
Copyright © 2020-2023  润新知