【BZOJ 2288】 2288: 【POJ Challenge】生日礼物 (贪心+优先队列+双向链表)

2288: 【POJ Challenge】生日礼物

Description

ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1A2, ..., AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物。

自然地,ftiasch想要知道选择元素之和的最大值。你能帮助她吗?

Input

第1行,两个整数 N (1 ≤ N ≤ 105) 和 M (0 ≤ M ≤ 105), 序列的长度和可以选择的部分。

第2行, N 个整数 A1A2, ..., AN (0 ≤ |Ai| ≤ 104), 序列。

Output

一个整数,最大的和。

Sample Input


5 2
2 -3 2 -1 2

Sample Output

5

HINT

Source

 

 

【分析】

  我好笨啊。。。

  首先可以把序列弄的好看点,0删掉,负数一段合并,正数一段合并。

  那么就是- + - + - 交替。

  假设我们先把所有正段选了。假设选了cnt段。

  如果cnt<=m,那么这显然就是答案。  

  否则,按照他们的绝对值扔进小根堆里面,每次选队顶元素。ans-=他的值。

  如果选到正数,表示把这个正数删掉,就少了一段。

  如果选到负数,表示把负数两边的两段连起来,也少了一段。

  知道这个意思之后就知道两端的负数是不可以选的,因为没有意义。

  然后删掉那个数之后和两边的两段合并起来重新扔到堆里面做。。【里面包含后悔操作!!!!思考一下!!!!

 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 using namespace std;
 8 #define Maxn 100100
 9 
10 struct node
11 {
12     int id,x;
13     friend bool operator < (node x,node y)
14     {
15         return x.x>y.x;
16     }
17 };
18 
19 priority_queue<node > q;
20 
21 int a[Maxn],w[2*Maxn];
22 int lt[2*Maxn],nt[2*Maxn];
23 bool mark[2*Maxn];
24 
25 int myabs(int x) {return x<0?-x:x;}
26 
27 int main()
28 {
29     int n,m;
30     scanf("%d%d",&n,&m);
31     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
32     w[1]=a[1];
33     int p=1;
34     for(int i=2;i<=n;i++)
35     {
36         if(a[i]==0) continue;
37         if((a[i]>=0&&w[p]>=0)||(a[i]<=0&&w[p]<=0)) w[p]+=a[i];
38         else w[++p]=a[i];
39     }
40     int cnt=0,ans=0;
41     for(int i=1;i<=p;i++) if(w[i]>0) cnt++,ans+=w[i];
42     if(cnt>m)
43     {
44         m=cnt-m;
45         memset(mark,0,sizeof(mark));
46         while(!q.empty()) q.pop();
47         for(int i=1;i<=p;i++) nt[i]=i+1;nt[p]=-1;
48         for(int i=1;i<=p;i++) lt[i]=i-1;
49         for(int i=1;i<=p;i++)
50         {
51             node xx;
52             xx.id=i;
53             xx.x=myabs(w[i]);
54             q.push(xx);
55         }
56         cnt=p;
57         for(int i=1;i<=m;i++)
58         {
59             while(mark[q.top().id]) q.pop();
60             node xx=q.top();q.pop();
61             if(lt[xx.id]==0)
62             {
63                 lt[nt[xx.id]]=0;
64                 if(w[xx.id]<0)
65                 {
66                     i--;
67                     continue;
68                 }
69                 ans-=xx.x;
70             }
71             else if(nt[xx.id]==-1)
72             {
73                 nt[lt[xx.id]]=-1;
74                 if(w[xx.id]<0)
75                 {
76                     i--;
77                     continue;
78                 }
79                 ans-=xx.x;
80             }
81             else
82             {
83                 ans-=xx.x;
84                 mark[lt[xx.id]]=mark[nt[xx.id]]=1;
85                 cnt++;
86                 nt[lt[lt[xx.id]]]=lt[nt[nt[xx.id]]]=cnt;
87                 lt[cnt]=lt[lt[xx.id]];nt[cnt]=nt[nt[xx.id]];
88                 node nw;
89                 nw.id=cnt;
90                 nw.x=myabs(w[nt[xx.id]]+w[lt[xx.id]]+w[xx.id]);
91                 w[cnt]=w[nt[xx.id]]+w[lt[xx.id]]+w[xx.id];
92                 q.push(nw);
93             }
94         }
95     }
96     printf("%d\n",ans);
97     return 0;
98 }
View Code

 

 

给一个sample

in:
5
53 -20 3 -27 68

out:
77

 

发发表情更健康

 

 

 

2017-01-14 11:01:57

posted @ 2017-01-14 11:00  konjak魔芋  阅读(308)  评论(3编辑  收藏  举报