zoukankan      html  css  js  c++  java
  • 洛谷 P1792 [国家集训队]种树

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

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

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

    我们每次肯定是选美观值最大的位置种,然后考虑相邻的位置不能种的限制,可以考虑反悔贪心,假如我们选了(i)这个位置,设(i)左右两边的位置为(l_i,r_i),我们把(a_{r_i}+a_{l_i}-a_i)加进去,相当于把这三个合并成一个,这样下次如果选到这个就相当于选了(l_i,r_i)两个位置了。

    这个过程可以用双向链表轻松实现。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #define mp make_pair
    #define fi first
    #define se second
    const int N = 5e5;
    using namespace std;
    int n,k,nxt[N + 5],pre[N + 5],vis[N + 5];
    long long ans,a[N + 5];
    priority_queue <pair<long long,int> > q;
    int main()
    {
        scanf("%d%d",&n,&k);
        if (k > n / 2)
        {
            cout<<"Error!"<<endl;
            return 0;
        }
        for (int i = 1;i <= n;i++)
            scanf("%lld",&a[i]);
        for (int i = 1;i <= n;i++)
        {
            nxt[i] = i + 1;
            pre[i] = i - 1;
            q.push(mp(a[i],i));
        }
        pre[1] = n;
        nxt[n] = 1;
        for (int i = 1;i <= k;i++)
        {
            while (vis[q.top().se])
                q.pop();
            ans += q.top().fi;
            int u = q.top().se;
            q.pop();
            a[u] = a[pre[u]] + a[nxt[u]] - a[u];
            vis[pre[u]] = vis[nxt[u]] = 1;
            nxt[pre[pre[u]]] = u;
            pre[nxt[nxt[u]]] = u;
            pre[u] = pre[pre[u]];
            nxt[u] = nxt[nxt[u]];
            q.push(mp(a[u],u));
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    生产者消费者问题--进阶
    互斥量和信号量的区别
    linux多线程大神博客网址
    生产者消费者
    文件互斥
    Linux中link,unlink,close,fclose详解
    条件变量
    哲学家进餐问题-3中解决方案
    使用读写锁解决读者-写者问题
    架构漫谈(三):如何做好架构之识别问题
  • 原文地址:https://www.cnblogs.com/sdlang/p/13956003.html
Copyright © 2011-2022 走看看