• 【bzoj2151】种树(堆/优先队列+双向链表)


      题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2151

      这道题因为优先队列不怎么会用,而且手写堆的代码也不长,也想复习一下手写堆的写法……结果……WAWAWAWAW……看来我对堆的认识还是太浅薄了……

      这道题,如果没有限制不能选相邻的两个位置,那就肯定是贪心地选择m个美观度最大的位置种树。然而这里加了限制,那么我们可以注意到,如果一个美观度比较大的位置不被选上,一定是因为它两边的位置都被选了。

      于是我们可以把n个美观度压进一个堆里,每次把美观度最大的位置取出来更新答案,然后它两边的位置删掉,把这个位置的美观度修改成(左边的美观度+右边的美观度-原美观度),就是选这个位置与选两边位置的权值差。

      如果细节没有打错,然后就可以愉快地AC这道题了。

      跑的慢也不会赢的代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<ctime>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<map>
    #define ll long long
    #define inf 1<<30;
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    ll read()
    {
        ll tmp=0; char f=1,c=getchar();
        while(c<'0'||'9'<c){if(c=='-')f=-1; c=getchar();}
        while('0'<=c&&c<='9'){tmp=tmp*10+c-'0'; c=getchar();}
        return tmp*f;
    }
    using namespace std;
    struct data{
        int w,id;
    }hp[200010];
    int l[200010],r[200010],pos[200010];
    int n,m,tot=0;
    void swap(int x,int y)
    {
        data tmp=hp[x]; hp[x]=hp[y]; hp[y]=tmp;
        pos[hp[x].id]=x; pos[hp[y].id]=y;
    }
    void add(int id,int w)
    {
        hp[++tot].id=id; hp[tot].w=w; pos[id]=tot;
        for(int now=tot;now>1&&hp[now].w>hp[now>>1].w;now>>=1)swap(now,now>>1);
    }
    void sift(int x)
    {
        int now=x;
        while(now<<1<=tot){
            int ne=now<<1;
            if(ne<tot&&hp[ne].w<hp[ne+1].w)++ne;
            if(hp[ne].w>hp[now].w)swap(ne,now),now=ne;
            else break;
        }
    }
    void del(int id)
    {
        hp[pos[id]].w=-inf; sift(pos[id]); 
        r[l[id]]=r[id]; l[r[id]]=l[id];
    }
    int main()
    {
        int i;
        n=read(); m=read();
        if(n<m*2){
            printf("Error!
    "); return 0;
        }
        for(i=1;i<=n;i++)add(i,read()),l[i]=i-1,r[i]=i+1;
        l[1]=n; r[n]=1;
        ll ans=0;
        while(m--){
            ans+=hp[1].w;
            int id=hp[1].id;
            hp[1].w=hp[pos[l[id]]].w+hp[pos[r[id]]].w-hp[1].w; sift(1);
            del(l[id]); del(r[id]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    bzoj2151
  • 相关阅读:
    1.18
    人月神话读后感
    疯狂学java的第45天
    学Java的第46天
    JAVA学习日记150720
    JAVA学习日记140719
    JAVA学习日记160721
    JAVA学习日记130718
    Windows DOS窗体下Oracle 数据库的导入导出(IMP/EXP)命令
    IntelliJ IDEA自动清除没用的import
  • 原文地址:https://www.cnblogs.com/quzhizhou/p/8079769.html
Copyright © 2020-2023  润新知