zoukankan      html  css  js  c++  java
  • 洛谷P1792 [国家集训队]种树(链表 贪心)

    题意

    题目链接

    Sol

    最直观的做法是wqs二分+dp。然而还有一种神仙贪心做法。

    不难想到我们可以按权值从大到小依次贪心,把左右两边的打上标记,但这显然是错的比如(1 231 233 232)。我们会得到(234)而不是(463)。考虑加入一种反悔机制,也就是说我们可以增加一种决策来取消该决策的影响并加入新的决策的贡献。

    考虑这样一种做法:把原来的点权改为(231 + 232 - 233),并用双向链表维护前驱后继。把(233)的前驱改为(231)的前驱并把(233)的后继改为(232)的后继。这样我们再次选择这个点的贡献的时候就相当于选了(231 +232)

    复杂度(O(nlogn))

    // luogu-judger-enable-o2
    #include<bits/stdc++.h> 
    #define Pair pair<int, int>
    #define MP(x, y) make_pair(x, y)
    #define fi first
    #define se second
    #define LL long long 
    #define ull unsigned long long 
    #define Fin(x) {freopen(#x".in","r",stdin);}
    #define Fout(x) {freopen(#x".out","w",stdout);}
    using namespace std;
    const int MAXN = 1e6 + 10, mod = 1e9 + 7, INF = 1e9 + 10;
    const double eps = 1e-9;
    template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;}
    template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;}
    template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;}
    template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);}
    template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;}
    template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;}
    template <typename A> inline void debug(A a){cout << a << '
    ';}
    template <typename A> inline LL sqr(A x){return 1ll * x * x;}
    inline int read() {
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int N, M, a[MAXN], pre[MAXN], nxt[MAXN], vis[MAXN], cnt;
    priority_queue<Pair> q;
    signed main() {
        N = read(); M = read();
        if(M > N / 2) {puts("Error!"); return 0;}
        for(int i = 1; i <= N; i++) a[i] = read(), pre[i] = i - 1, nxt[i] = i + 1, q.push({a[i], i});
        pre[1] = N; nxt[N] = 1;
     	int ans = 0;
        while(M--) {
     		Pair p = q.top(); q.pop(); int c = p.se;
            if( vis[c]) {M++; continue;}	
     		ans += p.fi;
            a[c] = a[pre[c]] + a[nxt[c]] - a[c]; vis[pre[c]] = 1; vis[nxt[c]] = 1;
            pre[c] = pre[pre[c]]; nxt[c] = nxt[nxt[c]];
            nxt[pre[c]] = c; pre[nxt[c]] = c;
            q.push({a[c], c});
        }
        cout << ans;
        return 0;
    }
    /*
    2
    1 1
    */
    
  • 相关阅读:
    static 关键字
    gitlab 配置到jenkins
    Eclipse下代码字体背景变红/变绿/变黄原因
    构造方法(和python初始化变量类似)
    面向对象(实际就像python跳用自己写的库那样)
    Python 的AES加密与解密
    break 和 continue 的用法
    for循环
    Eclipse快捷键
    java三元运算符
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/10488210.html
Copyright © 2011-2022 走看看