• [国家集训队]种树


    题目描述

    A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。

    园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。

    最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。

    输入输出格式

    输入格式:

    输入的第一行包含两个正整数n、m。第二行n个整数Ai。

    输出格式:

    输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。

    输入输出样例

    输入样例#1:

    7 3
    1 2 3 4 5 6 7

    输出样例#1:

    15

    输入样例#2:

    7 4
    1 2 3 4 5 6 7

    输出样例#2:

    Error!

    说明

    对于全部数据:m<=n;

    -1000<=Ai<=1000

    刚看到这题第一反应是DP。。然而瞅了一眼数据范围(emm,200000)

    发现是一个贪心。。思路非常神奇。。

    就是以在每个坑种树的收益建一个大根堆

    然后用链表存它的前驱后继(n的后继为1,1的前驱为n)

    每次取最大的收益。

    那么问题来了————有可能在这个点种树比在它两边各种一棵树收益小。

    但一定是两边各种一棵,因为我们建的是大根堆,先出来的一定大。

    所以我们可以选这个坑种树,也可以选两边的坑各种一棵,所以我们给我们的贪心一个反悔的机会

    就是选在这个坑种树以后将它两边的坑合并为一个价值为(w[l]+w[r]-w[now])的坑,代替我们选择的坑

    这里非常的巧妙,就是如果选了这个坑就相当于不在那个中间的坑种树了,而是在它两边各种一棵。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    # define M (200000+50)
    using namespace std;
    struct node{
        int value,place;
        friend bool operator < (node x,node y){
            return x.value < y.value;
        }
    };
    priority_queue<node> q;
    int n,m,Ans,chose,nxt[M],pre[M],w[M],l,r;
    bool vis[M];
    void change(int x){
        vis[x]=1;
        nxt[pre[x]]=nxt[x];
        pre[nxt[x]]=pre[x];
        nxt[x]=0; pre[x]=0;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)  {
          scanf("%d",&w[i]);
        }
        if((n>>1)<m){
            cout<<"Error!"<<endl;
            return 0;
        }
        for(int i=1;i<n;i++) nxt[i]=i+1; nxt[n]=1;
        for(int i=2;i<=n;i++) pre[i]=i-1; pre[1]=n;
        for(int i=1;i<=n;i++) q.push((node){w[i],i});
        for(int i=1;i<=m;i++){
            while(vis[q.top().place]) q.pop() ;
            node temp = q.top(); q.pop();
            Ans+= temp.value;
            l=pre[temp.place];   r=nxt[temp.place];
            w[temp.place]=w[l]+w[r]-w[temp.place];
            change(l);    change(r);
            q.push((node){w[temp.place],temp.place});
        }
        printf("%d
    ",Ans);
        return 0;
    }
    
  • 相关阅读:
    【rust】Rust 的构建系统和包管理工具Cargo认识并初步使用(2)
    【rust】rust安装,运行第一个Rust 程序 (1)
    linux 双网卡桥接,实现网卡流量镜像与转发
    【原创】使用golang访问windows telnet服务器
    使用centos 7安装conpot
    用Redis作Mysql数据库缓存
    python解析处理snmp回显----snmp
    snmp自定义OID与文件下载----服务器端配置
    golang map输出排序
    计算机组成原理---第1章 计算机系统概述
  • 原文地址:https://www.cnblogs.com/beretty/p/9478660.html
Copyright © 2020-2023  润新知