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;
    }
    欢迎转载,转载请注明出处!
  • 相关阅读:
    QOMO Linux 4.0 正式版发布
    LinkChecker 8.1 发布,网页链接检查
    pgBadger 2.1 发布,PG 日志分析
    Aletheia 0.1.1 发布,HTTP 调试工具
    Teiid 8.2 Beta1 发布,数据虚拟化系统
    zLogFabric 2.2 发布,集中式日志存储系统
    开源电子工作套件 Arduino Start Kit 登场
    Piwik 1.9 发布,网站访问统计系统
    Ruby 1.9.3p286 发布,安全修复版本
    toBraille 1.1.2 发布,Java 盲文库
  • 原文地址:https://www.cnblogs.com/huihao/p/7445721.html
Copyright © 2011-2022 走看看