zoukankan      html  css  js  c++  java
  • bzoj2288【POJ Challenge】生日礼物*

    bzoj2288【POJ Challenge】生日礼物

    题意:

    给一个序列,求不超过m个连续的部分,使元素和最大。序列大小≤100000

    题解:

    先把连续的正数和负数合并起来,接着如果正数个数小于m则全选,否则需要确定去掉那个正数或合并哪个正数。初始ans设为所有正数和,将所有的数按绝对值大小放入堆中,然后重复m-正数个数操作:每次选取绝对值最小的数,如果是负数且它在边界处则重新选,否则将这个数删除并将两边的数合并,同时ans-=该数绝对值。该操作的意义在于:如果删去的是正数表示不选它,否则表示选这个负数以将左右的的正数合并起来。类似于1150,我用链表和STLset维护这个过程。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <set>
     5 #define inc(i,j,k) for(int i=j;i<=k;i++)
     6 #define maxn 100010
     7 using namespace std;
     8 
     9 inline int read(){
    10     char ch=getchar(); int f=1,x=0;
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    12     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    13     return f*x;
    14 }
    15 int n,m,a[maxn],b[maxn],tot,ans;
    16 struct sn{
    17     int pos,v;
    18     bool operator < (const sn &x)const{return v!=x.v?v<x.v:pos<x.pos;}
    19 };
    20 set<sn>s;
    21 struct nd{int v,l,r; bool bit;}; nd nds[maxn];
    22 int main(){
    23     n=read(); m=read(); inc(i,1,n)b[i]=read();
    24     int last=0; inc(i,1,n){
    25         if(b[i]==0)continue; if(!last||(last>0^b[i]>0))a[++tot]=b[i];else a[tot]+=b[i]; last=b[i];
    26     }
    27     n=tot; tot=0; inc(i,1,n)if(a[i]>0)tot++,ans+=a[i];
    28     if(tot>m){
    29         inc(i,1,n){s.insert((sn){i,abs(a[i])}); nds[i]=(nd){abs(a[i]),i-1,i+1>n?0:i+1,a[i]>0};}
    30         inc(i,1,tot-m){
    31             set<sn>::iterator xx; int x;
    32             while(1){
    33                 xx=s.begin(); x=xx->pos; s.erase(xx);
    34                 if((!nds[x].l||!nds[x].r)&&!nds[x].bit){
    35                     if(!nds[x].l)nds[nds[x].r].l=0; if(!nds[x].r)nds[nds[x].l].r=0;
    36                 }else break;
    37             }
    38             ans-=nds[x].v;
    39             if(!nds[x].l&&!nds[x].r)continue;
    40             else if(!nds[x].r)nds[nds[x].l].r=0;
    41             else if(!nds[x].l)nds[nds[x].r].l=0;
    42             else{
    43                 nds[x].v=nds[nds[x].l].v+nds[nds[x].r].v-nds[x].v; nds[x].bit=nds[nds[x].l].bit;
    44                 xx=s.find((sn){nds[x].l,nds[nds[x].l].v}); s.erase(xx);
    45                 xx=s.find((sn){nds[x].r,nds[nds[x].r].v}); s.erase(xx);
    46                 s.insert((sn){x,nds[x].v});
    47                 nds[x].l=nds[nds[x].l].l; nds[x].r=nds[nds[x].r].r; nds[nds[x].l].r=x; nds[nds[x].r].l=x;
    48             }
    49         }
    50     }
    51     printf("%d",ans); return 0;
    52 }

    20160905

  • 相关阅读:
    Gym
    Gym
    Gym
    Gym
    Gym
    hdu2586 LCA带边权的Targan算法
    bryce1010专题训练——LCA
    POJ1470 LCA (Targan离线)
    bryce1010专题训练——LCT&&树链剖分
    模板——2.7 欧拉函数
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5861750.html
Copyright © 2011-2022 走看看