zoukankan      html  css  js  c++  java
  • [bzoj2288][POJ Challenge]生日礼物

      用堆维护双向链表来贪心。。。

      数据范围显然不容许O(nm)的傻逼dp>_<。。而且dp光是状态就n*m个了。。显然没法优化

      大概就会想到贪心乱搞了吧。。。一开始想贪心地通过几段小的负数把正数连接成一段,但到底是要连接在一起还是直接扔掉不好判断

      然后就跑去翻题解了。。。题解讲的挺好的,连我都看懂了>_<。。题解网址:http://www.cnblogs.com/tuigou/p/4868127.html

      虽然选正数和负数的意义不同,但实际的操作都是把两边的数合并起来。还有就是,对于在左端或右端的负数,把它删去后并不会减少当前选取的段数。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<cstdlib>
     7 #include<cmath>
     8 #define ll long long
     9 using namespace std;
    10 const int maxn=100233;
    11 struct zs{
    12     int id;
    13 };
    14 priority_queue <zs>q;
    15 int a[maxn],cnt,pre[maxn<<1],next[maxn<<1],v[maxn<<1];
    16 int i,j,n,m,zsnum,ans;
    17 bool del[maxn<<1];
    18 
    19 int ra,fh;char rx;
    20 inline int read(){
    21     rx=getchar(),ra=0,fh=1;
    22     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
    23     if(rx=='-')fh=-1,rx=getchar();
    24     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
    25 }
    26 bool operator <(zs a,zs b){return abs(v[a.id])>abs(v[b.id]);}
    27 int main(){
    28     n=read(),m=read();if(!m){puts("0");return 0;}
    29     for(i=1;i<=n;i++)a[i]=read();cnt=0;
    30     for(i=1;i<=n;v[cnt]+=a[i++])
    31         if((ll)a[i]*(ll)v[cnt]<0||!cnt)cnt++;
    32     for(i=1;i<=cnt;i++)if(v[i]>0)zsnum++,ans+=v[i];
    33     if(zsnum>m){
    34         for(i=1;i<=cnt;i++)q.push((zs){i}),pre[i]=i-1,next[i]=i+1;//,printf("  %d",v[i]);puts("");
    35         pre[1]=next[cnt]=0;
    36         for(i=zsnum-m;i;i--){
    37             while(!q.empty()&&del[q.top().id])q.pop();if(q.empty())break;
    38             int x=q.top().id,pr=pre[x],nex=next[x];
    39             
    40             q.pop(),ans-=abs(v[x]),del[x]=1;
    41             if(!(pr&&nex)){
    42                 if(v[x]<0)i++,ans+=abs(v[x]);
    43                 if(pr)next[pr]=0;if(nex)pre[nex]=0;
    44             }
    45             else{
    46                 del[pr]=del[nex]=1;
    47                 v[++cnt]=v[pr]+v[x]+v[nex];
    48                 q.push((zs){cnt});
    49                 if(pre[pr])pre[cnt]=pre[pr],next[pre[cnt]]=cnt;
    50                 if(next[nex])next[cnt]=next[nex],pre[next[cnt]]=cnt;
    51             }
    52         }
    53     }
    54     printf("%d
    ",ans);
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    ubuntu基本命令篇13用户管理
    网易邮箱繁体字信件乱码解决
    ubuntu基本命令篇16网络管理
    Ubuntu 10.04的安装
    DotNetNuke模块开发(一)
    查询进程打开的文件(转)
    Shell 的变量(转)
    Boot loader: Grub进阶(转)
    bash的通配符与特殊符号
    shell下的作业管理(转)
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5185807.html
Copyright © 2011-2022 走看看