码迷,mamicode.com
首页 > 其他好文 > 详细

51nod1380 夹克老爷的逢三抽一

时间:2018-08-30 11:06:59      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:struct   void   贪心   .com   复杂度   push   fread   efi   main   

技术分享图片

问题等价于选出$n / 3$个不相邻元素是权值和最大

这是一个经典贪心问题,同种树,拿堆维护即可,复杂度$O(n \log n)$

#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;

extern inline char gc() {
    static char RR[23456], *S = RR + 23333, *T = RR + 23333;
    if(S == T) fread(RR, 1, 23333, stdin), S = RR;
    return *S ++;
}
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > 9 || c < 0) { if(c == -) w = -1; c = gc(); }
    while(c >= 0 && c <= 9) p = p * 10 + c - 0, c = gc();
    return p * w;
}

#define ll long long
#define ri register int
#define sid 200050

int n, k;
bool gg[sid];
ll ans, v[sid], pre[sid], nxt[sid];

struct Man {
    ll id, val;
    Man() {}
    Man(ll _i, ll _v) : id(_i), val(_v) {}
    friend bool operator < (Man a, Man b)
    { return a.val < b.val; }
} ;
priority_queue <Man> q;

inline void del(int o) {
    pre[nxt[o]] = pre[o];
    nxt[pre[o]] = nxt[o];
    gg[o] = 1;
}

int main() {
    n = read();
    for(ri i = 1; i <= n; i ++) v[i] = read();
    
    for(ri i = 1; i <= n; i ++) {
        pre[i] = i - 1; nxt[i] = i + 1;
        q.push(Man(i, v[i]));
    }
    pre[1] = n; nxt[n] = 1;

    k = n / 3;
    for(ri i = 1; i <= k; i ++) {
        Man o; int id;
        while(1) {
            o = q.top(); q.pop();
            id = o.id; if(!gg[id]) break;
        }
        ans += v[id];
        v[id] = v[pre[id]] + v[nxt[id]] - v[id];
        q.push(Man(id, v[id]));
        del(pre[id]); del(nxt[id]);
    }
    printf("%lld\n", ans);
    return 0;
}

 

51nod1380 夹克老爷的逢三抽一

标签:struct   void   贪心   .com   复杂度   push   fread   efi   main   

原文地址:https://www.cnblogs.com/reverymoon/p/9558001.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!