• bzoj2288: 【POJ Challenge】生日礼物


    心态都崩了做了一上午。。。

    首先想的就是把连续同正负性的合并起来,那么相邻数的正负性是反的。

    然后我想的是建一个链表倒着删除到m

    这个时候有一个奇妙的想法,把正的取和,放进链表里面的数都取绝对值,假如删掉正的可以看作少了一段,删掉负的可以看作把两个正的连在一起,按照数据备份那个退流的思想做

    尴尬的是我发现我不会判边界,冥冥中记忆是在两边放哨兵节点,没写硬判fail得头皮发麻,结果是%了一发自己。。

    upd:第二次做的时候就感觉好很多了。首先是先想了想DP,结果发现状态数都要nm没办法再优化了

    然后考虑下这种链表类似退流的毒瘤题……

    连续的正负显然是分成一组,然后就自然而然的想到和上面一样倒着玩。。。(果然是本人)

    正数是收益,负数是代价显然很不资瓷(貌似资瓷这个东西的只有最大权闭合图?),早上做了一道很类似的转换问题的方法,我们希望的是收益最大,那么先正数取sum,然后再减去小的,这样问题就转换成选取代价最小的了,按照数据备份的做法做就可以了~(这次代码写的也好看一些啊)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    using namespace std;
    
    struct node
    {
        int c,me,b;
        bool friend operator>(node n1,node n2){return n1.c>n2.c;}
    }a[110000];int len,bef[110000],aft[110000];
    priority_queue<node,vector<node>,greater<node> >q;
    void ins(int ss)
    {
        if(len==1&&ss<0)return ;
        len++;
        a[len].c=abs(ss);a[len].me=len;a[len].b=1;
    //    printf("%d ",a[len].c);
        q.push(a[len]);
        bef[len]=len-1, aft[len]=len+1;
    }
    
    int c[110000];bool v[110000];
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int n,m;
        scanf("%d%d",&n,&m);
        if(m==0){printf("0
    ");return 0;}
        
        int ss=0,sum=0;len=0;
        ins(1<<30);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&c[i]);
            if((ss>=0&&c[i]>=0)||(ss<=0&&c[i]<=0))ss+=c[i];
            else 
            {
                ins(ss);
                if(ss>0)sum+=ss;
                ss=c[i];
            }
        }
        if(ss>0)ins(ss),sum+=ss;
        ins(1<<30);
        bef[1]=-1;aft[len]=-1;
    
        if((len+1)/2<=m){printf("%d
    ",sum);return 0;}
        int mmax=0;node t;bool zz1=false,zz2=false;
        memset(v,true,sizeof(v));
        for(int i=len/2-1;i>=1;i--)
        {
            t=q.top();q.pop();
            while(v[t.me]==false)t=q.top(),q.pop();
            sum-=t.c;
            if(i<=m)mmax=max(mmax,sum);
            
            t.c=-t.c;
            if(bef[t.me]!=-1) v[bef[t.me]]=false, t.c+=a[bef[t.me]].c, bef[t.me]=bef[bef[t.me]];
            if(aft[t.me]!=-1) v[aft[t.me]]=false, t.c+=a[aft[t.me]].c, aft[t.me]=aft[aft[t.me]];
            if(bef[t.me]!=-1) aft[bef[t.me]]=t.me;
            if(aft[t.me]!=-1) bef[aft[t.me]]=t.me;
            a[t.me].c=t.c;
            
            q.push(t);
            if(q.top().c>0&&i<=m)break; 
        }
        printf("%d
    ",mmax);
        return 0;
    }
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    using namespace std;
    
    int n,m,a[110000];
    int len,c[110000],bef[110000],aft[110000];
    struct node
    {
        int d,id;
        node(){}
        node(int D,int ID){d=D,id=ID;}
        friend bool operator >(node n1,node n2){return n1.d>n2.d;}
        friend bool operator <(node n1,node n2){return n1.d<n2.d;}
    };priority_queue<node,vector<node>,greater<node> >q;
    bool inq[110000];
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int ans=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]==0)i--,n--;
            else if(a[i]>0)ans+=a[i];
        }
        
        int sum=0,op=0,cnt=0; len=0;
        for(int i=1;i<=n;i++)
        {
            if(a[i]>0)
            {
                if(op==1)
                {
                    if(len!=0)c[++len]=sum;
                    sum=0, op=0;
                }
                sum+=a[i];
                
            }
            else 
            {
                if(op==0)
                {
                    if(sum!=0)c[++len]=sum,cnt++;
                    sum=0, op=1;
                }
                sum+=-a[i];
            }    
        }
        if(op==0)c[++len]=sum,cnt++;
        
        c[0]=c[len+1]=(1<<30);
        for(int i=1;i<=len;i++)
        {
            bef[i]=i-1,aft[i]=i+1;
            q.push(node(c[i],i));inq[i]=true;
        }
        
        for(int i=1;i<=cnt-m;i++)
        {
            while(inq[q.top().id]==false)q.pop();
            int k=q.top().id;q.pop();
            int lc=bef[k],rc=aft[k];
            
            ans-=c[k];
            c[k]=c[lc]+c[rc]-c[k];
            bef[k]=bef[lc],aft[k]=aft[rc];
            aft[bef[k]]=k, bef[aft[k]]=k;
            inq[lc]=inq[rc]=false;
            q.push(node(c[k],k));
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    叨叨叨
    四舍五入VS银行家舍入
    是雏还是鹰&mdash;&mdash;编程规范之变量命名
    .Net下二进制形式的文件(图片)的存储与读取(原创)
    asp.net中<%%>形式的用法(原创)
    让Hashtable支持自定义排序(原创)
    .NET下的迭代器(Iterator)模式
    本地视频播放-ios
    cocos2dx srand(time(NULL))重新设置一个随机种子
    cocos2dx 游戏重置方法
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9262281.html
Copyright © 2020-2023  润新知