zoukankan      html  css  js  c++  java
  • BZOJ 2288: 【POJ Challenge】生日礼物 堆&&链表

    就是堆+链表,十分像 数据备份 对吧?

    把相邻的正数和相邻的负数合并成一整个正数块和负数块,最后只剩一些交替相间的正块与负块了吧?

    显然,正块的个数<=m时,全部选走就获得了最大权值,否则我们可能需要选一些负块来获得最优解。

    然而弱不经风的我调了四个小时链表和预处理QAQ。。。

    千万不要犯此种错误:

        n=g(),m=g();
        for(R i=1;i<=n;++i) a[i]=g();
        vl[cnt]=a[1],pre[0]=0;
        for(R i=2;i<=n;++i) if(sgn(a[i])==sgn(a[i-1])&&sgn(a[i])) vl[cnt]+=a[i];//,cnt==1?cerr<<"%"<<vl[cnt]<<" ":cerr<<"";
            else if(sgn(a[i]))vl[++cnt]=a[i],nxt[cnt-1]=cnt,pre[cnt]=cnt-1; nxt[cnt]=0;

    上面这种写法会吧中间有0的同号块分成两块。。。。

    AC代码:

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #define R register int
    using namespace std;
    const int N=100010; 
    int cnt,n,m,pst,neg,tot,ans=0;
    int a[N],vl[N],pre[N],nxt[N];
    bool vis[N];
    struct node{
        int vl,pos;
        node() {}
        node(int vvl,int ppos):vl(vvl),pos(ppos){}
        bool operator <(const node& y)const {return vl>y.vl;}
    };
    priority_queue<node> q;
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
    inline int abs(int x) {return x>0?x:-x;}
    signed main() {
        n=g(),m=g();
        for(R i=1;i<=n;++i) {
            a[i]=g();
            if(a[i]>0){pst+=a[i]; neg&&cnt?vl[++cnt]=neg,neg=0:neg=0;}
            if(a[i]<0){neg+=a[i]; pst?vl[++cnt]=pst,pst=0:pst=0;}
        } pst?vl[++cnt]=pst:pst=0;
        for(R i=1;i<=cnt;++i) {
            q.push(node(abs(vl[i]),i));
            vl[i]>0?++tot,ans+=vl[i]:vl[i]=-vl[i];
            nxt[i]=i+1,pre[i]=i-1;
        } nxt[cnt]=0;
        for(R i=1;i+m<=tot;++i) {
            register node tmp=q.top();q.pop();
            while(vis[tmp.pos]&&!q.empty()) tmp=q.top(),q.pop();
            if(vis[tmp.pos]) break;
            ans-=tmp.vl; if(q.empty()) break;
            R pos=tmp.pos;
            if(!pre[pos]) vis[nxt[pos]]=vis[pos]=true,pre[nxt[nxt[pos]]]=0;
            else if(!nxt[pos]) vis[pre[pos]]=vis[pos]=true,nxt[pre[pre[pos]]]=0;
            else {
                vis[pre[pos]]=vis[nxt[pos]]=true;
                tmp.vl=vl[pos]=vl[pre[pos]]+vl[nxt[pos]]-vl[pos];
                if(nxt[nxt[pos]]) pre[nxt[nxt[pos]]]=pos;
                if(pre[pre[pos]]) nxt[pre[pre[pos]]]=pos;
                pre[pos]=pre[pre[pos]],nxt[pos]=nxt[nxt[pos]];
                q.push(tmp);
            }
        } printf("%d
    ",ans);
    }

    2019.04.06

  • 相关阅读:
    我就是想找个人聊聊天,说说我这近四年来的经历-02
    我就是想找个人聊聊天,说说我这近四年来的经历
    Padas交叉表新增二级分类小计
    superset开启本地缓存filesystem
    Superset连接Impala数据源
    Python实现网站注册验证码生成类
    Python爬虫原理
    Superset导出pivot_table到excel
    Superset导出CSV文件中文或日文乱码
    Linux下如何高效删除一个几十G的文本文件的最后一行或几行
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10660598.html
Copyright © 2011-2022 走看看