zoukankan      html  css  js  c++  java
  • Jzoj4726 种花

    相信大家都猜到题意了,简单说一下

    圆形广场共有 N 个种花的位置,顺时针编号1到N。并且每个位置都有一个美观度ai ,两株花不能种在相邻的位置(1号和N号也算相邻位置)一共有 M 株花,现在小D也想知道应该如何摆这 N 株花才能使美观度最大

    这道题显然可以用堆,每次将堆顶最大的元素取出并删除两边的元素

    但是正确性显然有问题,比如10,11,10,1显然答案是20而不是12

    那么每次,我们取出一个节点i后,要向堆里增加一个“撤回”节点,其位置i不变,但是值v[i]变为v[i-1]+v[i+1]-v[i],同时删除i-1,i+1两个节点,这样的话,我们就需要一个双向链表来维护左右节点是否被选择,l[i]表示i左边第一个没有备选的节点,r[i]类似

    流程:

    1.取出节点(i,v[i])

    2.删除l[i],r[i],并将l[l[i]]以及r[r[i]]与i相连

    3.向堆里加入节点(i,v[l[i]]+v[r[i]]-v[i]),那么如果取出这个节点,就相当于放弃i,而改为选择l[i]和r[i]

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    struct flower{ int id,x; };
    inline bool operator < (flower a,flower b){ return a.x<b.x; }
    int l[200010],r[200010],d[200010],w[200010],n,m,ans=0;
    priority_queue<flower> q;
    int main(){
    	scanf("%d%d",&n,&m);
    	if(n<m*2) return 0&puts("Error!");
    	for(int x,i=0;i<n;++i){
    		scanf("%d",&x);
    		q.push((flower){i,w[i]=x});
    		l[i]=(i-1+n)%n;
    		r[i]=(i+1)%n;
    	}
    	for(int i=0,j;i<m;++i){
    		flower a=q.top(); q.pop();
    		if(d[j=a.id]){ --i; continue; }
    		ans+=a.x; q.push((flower){j,w[j]=(w[l[j]]+w[r[j]]-a.x)});
    		r[l[l[j]]]=j; l[r[r[j]]]=j;
    		d[l[j]]=1; d[r[j]]=1;
    		l[j]=l[l[j]]; r[j]=r[r[j]];
    	}
    	printf("%d
    ",ans);
    }

  • 相关阅读:
    testd3p
    my open音频的
    1
    one play
    ndk ffmpeg实践2
    ndk ffmpeg实践
    Mac ndk21 交叉ffmpeg目前
    ffmpeg交叉
    and cmake 链接库及播放例子 及读文件
    更正之前《登录小案例》密码错3次15分钟内不准登录
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477301.html
Copyright © 2011-2022 走看看