zoukankan      html  css  js  c++  java
  • 【NOIp模拟赛】种花

    【问题描述】

    经过三十多个小时的长途跋涉,小Z和小D终于到了NOI现场——南山南中学。一进校园,小D就被花所吸引了(不要问我为什么),遍和一旁的种花园丁交(J)流(L)了起来。

    他发现花的摆放竟有如此奥秘:圆形广场共有 N个种花的位置,顺时针编号1到N。并且每个位置都有一个美观度,如果在这里种花就可以得到这的美观度。但由于地处南山土壤肥力欠佳,两株花不能种在相邻的位置(1号和N号也算相邻位置)。校方一共给了 M株花,经过园丁的精妙摆放,才能如此吸引小D。所以现在小D也想知道应该如何摆这 N株花。

    【输入格式】

    从文件 flower.in 中读入数据。

    输入第一行包含两个整数N,M

    接下来一行包含N个正整数,依次描述美观度。

    【输出格式】

    输出到文件 flower.out 中。

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

    【样例输入】

    7 3

    1 2 3 4 5 6 7

    【样例输出】

    15

    【数据规模与约定】

    对于50%的数据满足。

    对于100%的数据满足,。

    分析

    贪心+堆

    我们先把所有点放入堆中,每次取出美观度最大的。如果它不是最优解,那么它旁边的两个肯定是。

    这个可以用反证法来证明,如果它旁边的两个不是最优解,那么肯定可以选它,因为他是最大的。

    如果他旁边有一个是最优解一个不是最优解,这种情况肯定是不存在的,设它左边的不是最优解,左边肯定不影响,它现在是美观度最大的,选右边的还不如选它。

    每次取出最大之后讲
    V=Vpre+VnextV加入入堆,最后删掉PreNext,每次用堆维护,取出最大值即可。

    上面的公式是很巧妙的,也就是说如果它不是最优解还可以再选一次,只不过这次会把之前的v给减掉,加上它两边的和,而相比之前的那一次正好选了两次。

    代码

    手打的堆有点长不过速度比STL快。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=200000+5;
    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*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int n,m,heap_size,ans;
    int a[maxn],nxt[maxn],pre[maxn],heap[maxn];
    bool vis[maxn];
    inline void put(int x)
    {
        int now,nxt;
        heap[++heap_size]=x;
        now=heap_size;
        while(now>1)
        {
            nxt=now>>1;
            if(a[heap[now]]<=a[heap[nxt]]) break;
            int t=heap[now]; heap[now]=heap[nxt]; heap[nxt]=t;
            now=nxt;
        }
    }
    inline int get()
    {
        int now=1,nxt,res=heap[1];
        heap[1]=heap[heap_size--];
        while((now<<1)<=heap_size)
        {
            nxt=now<<1;
            if(nxt<heap_size&&a[heap[nxt+1]]>a[heap[nxt]]) nxt++;
            if(a[heap[now]]>=a[heap[nxt]]) break;
            int t=heap[now];heap[now]=heap[nxt]; heap[nxt]=t;
            now=nxt;
        }
        return res;
    }
    int main()
    {
        freopen("flower.in","r",stdin);
        freopen("flower.out","w",stdout);
        n=read(); m=read();
        if((m<<1)>n) { printf("Error!"); return 0;}
        for(int i=1;i<=n;i++) 
        { a[i]=read(); put(i);}
        for(int i=1;i<n;i++) nxt[i]=i+1;
        for(int i=2;i<=n;i++) pre[i]=i-1;
        nxt[n]=1; pre[1]=n;
        for(int i=1;i<=m;i++)
        {
            int x=get();
            while(vis[x])
                x=get();
            ans+=a[x];
            a[x]=a[pre[x]]+a[nxt[x]]-a[x];
            vis[pre[x]]=1; vis[nxt[x]]=1;
            put(x);
            nxt[x]=nxt[nxt[x]];
            pre[x]=pre[pre[x]];
            pre[nxt[x]]=x;
            nxt[pre[x]]=x;
        }
        printf("%d
    ",ans);
        return 0;
    }
    欢迎转载,转载请注明出处!
  • 相关阅读:
    Asp.net中利用ExecuteNonQuery()执行存储过程返回1解决方案
    在workflow中,无法为实例 ID“...”传递接口类型“...”上的事件“...” 问题的解决方法。
    jquery获取一个table中的一行的每个td的内容
    自动ping博客服务程序
    总结JavaScript(Iframe、window.open、window.showModalDialog)父窗口与子窗口之间的操作
    sql server try...catch使用
    IAsyncResult异步设计
    jquery 判断一个对象是否存在
    数据库表扩展字段设计思路
    REST接口POST方法发送文件到服务器(C#)
  • 原文地址:https://www.cnblogs.com/huihao/p/7445721.html
Copyright © 2011-2022 走看看