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

posted @ 2016-09-11 14:36  YuanZiming  阅读(154)  评论(0编辑  收藏  举报