codevs1342 种树

来源:互联网 发布:淘宝衣服搭配在哪里 编辑:程序博客网 时间:2024/06/05 09:55

题目

    A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。    最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。

解题思路

这个题拿到之后想了想dp,发现不行;为什么呢,因为每一个选或者不选,肯定要n^2的算法,那贪心?选最大的不行,因为可能两边值选了加起来比中间的大,所以我们加了最大的值之后可以退回来一个值,表示选两边的值。很明显,这个值就是a[i+1]-a[i]+a[i-1];如果选了这个值,说明选两边的值;可以用优先队列来存储`#include<queue>#include<cstdio>#include<iostream>#include<algorithm>using namespace std;const int N=200010; int n,m,a[N],be[N],af[N];//af表示这个位置前后面的位置,be表示前面的位置;bool vis[N];struct node{    int loc,v;}tmp[N];int tot;priority_queue<node>q; bool operator <(node a,node b){    return a.v<b.v;}int main(){    cin>>n>>m;    for(int i=1;i<=n;i++){        if(i==1)be[i]=n;        else be[i]=i-1;        if(i==n)af[i]=1;        else af[i]=i+1;        cin>>a[i];        node tmp;        tmp.loc=i;tmp.v=a[i];        q.push(tmp);    }    if(m>(n/2)){        cout<<"Error!";        return 0;    }    int ans=0;    for(int i=1;i<=m;i++){        node u=q.top();        q.pop();        while(vis[u.loc]){                u=q.top();                q.pop();        }        ans+=u.v;        int bex=be[u.loc],afx=af[u.loc];        vis[bex]=vis[afx]=true;        u.v=a[u.loc]=a[bex]+a[afx]-a[u.loc];        af[u.loc]=af[afx];be[u.loc]=be[bex];        be[af[afx]]=u.loc;af[be[bex]]=u.loc;        q.push(u);    }    cout<<ans<<endl;}`
0 0