A simple Blog for wyx I've been down the bottle hoping.
BZOJ 2151 种树 贪心 双向链表优化
发表于: | 分类: Oi | 评论:0 | 阅读:101

给你一个$n$个点的环,每个点有点权,在环上取出互不相邻的$m$个点,求最大值
我们可以贪心,将所有的点扔入一个堆里
每次取出堆顶的元素,然后在双向链表中删去这个点
然而这样可能是错的,比如$1 \quad 3 \quad 5 \quad 4$
正确答案应该是7
所以我们要给自己退路
在选择一个元素的时候,将该元素的值改为两边元素的和减去该元素,然后删去两边的元素
然后选择$m$次

我们来想他的正确性
首先:就算这两个不是最优的,我们下一次不会再选回来,一定可以保证答案的最优性
其次:我们不会选少,每次如果选出一个没选过的,肯定没问题,如果是一个选过的周边,也不会有什么问题,因为我们减去了原来的权值,保证了答案的完备性

其实画画就明白了,我就是没事瞎想的……总之对就是了
时间复杂度$mlog(n)$
TIPS 我的链表是数组的
所以喜欢指针的大神可以关掉页面了……

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#define N 200000+5
using namespace std;

inline int read()
{
    int x=0,f=1;char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-')f=-1;ch = getchar();}
    while(ch >='0' && ch <='9'){x=(x<<1)+(x<<3)+ch-'0';ch = getchar();}
    return x*f;
}

struct data
{
    int pos;
    int val;
    bool operator < (const data &z)const
    {
        return val < z.val;
    }
    data () {}
    data (int _pos,int _val)
    :pos(_pos),val(_val){}
};

priority_queue<data>Q;

int L[N],R[N],a[N];
bool del[N];
int ans = 0;

void work()
{
    while(del[Q.top().pos])
        Q.pop();
    data tmp = Q.top();Q.pop();
    int tt = tmp.pos;
    ans += a[tt];
    a[tt] = a[L[tt]] + a[R[tt]] - a[tt];
    Q.push(data(tt,a[tt]));
    R[L[L[tt]]] = tt;
    L[R[R[tt]]] = tt;
    del[R[tt]] = del[L[tt]] = 1;
    L[tt] = L[L[tt]];
    R[tt] = R[R[tt]];
}

int main()
{
    int n = read(), m = read();
    if(m > (n>>1)){puts("Error!");return 0;}
    for(int i=1;i<=n;++i)
    {
        a[i] = read();
        Q.push(data(i,a[i]));
        L[i] = i-1;
        R[i] = i+1;
    }
    L[1] = n;
    R[n] = 1;
    while(m--)
        work();
    cout<<ans;
}

Title - Artist
0:00

站点地图 网站地图
Copyright © 2015-2017 A simple Blog for wyx
Powered by Typecho自豪的采用Sgreen主题

TOP