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\n",ans);
}

 


 

2019.04.06

 

posted @ 2019-04-06 00:40  LuitaryiJack  阅读(146)  评论(0编辑  收藏  举报