BZOJ2288: 【POJ Challenge】生日禮物

2288: 【POJ Challenge】生日禮物

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 284  Solved: 82
[Submit][Status]

Description

 

ftiasch 18歲生日的時候,lqp18_31給她看了一個神奇的序列 A1, A2, ..., AN. 她被容許選擇不超過 M 個連續的部分做爲本身的生日禮物。php

天然地,ftiasch想要知道選擇元素之和的最大值。你能幫助她嗎?ios


Input

 

第1行,兩個整數 N (1 ≤ N ≤ 105) 和 M (0 ≤ M ≤ 105), 序列的長度和能夠選擇的部分。ide

第2行, N 個整數 A1, A2, ..., AN (0 ≤ |Ai| ≤ 104), 序列。spa

Output

 

 

一個整數,最大的和。code

Sample Input


5 2
2 -3 2 -1 2

Sample Output

5

HINT

Source

題解:blog

感受和數據備份這題有點像,可是又轉化不過來。。。看了hzwer的題解以後恍然大悟了。。。ip

首先連在一塊的正負相同的確定能夠當作一個點,而後咱們就獲得了一個正負交替的數列,而且首位兩項都是正數(負數去掉)get

而後若是正的項數<=m,那顯然咱們所有選走就得到了最大權值,不然咱們須要作一點犧牲。input

1)不選某些正項string

2)選一些負項使得相鄰的正項成爲1塊

記全部正數之和爲sum,咱們須要進行上面兩種操做使得sum減掉的數最小而且知足只有m塊。

咱們把全部數的絕對值放入一個堆,每次取最小元素x。sum'-=x

那麼若是該數原來是正的,意思是不選它;

若是是負的,意思是把它兩邊的正數合併。

但直接這樣作是不行的,咱們必須保證取負的時候兩邊的正的必須不被取,取正的時候兩邊的負的不被取。

換句話說,不能選擇相鄰的兩個數!咱們成功的將此題轉化成了數據備份問題。

orz!

代碼:

 1 #include<cstdio>
 2 
 3 #include<cstdlib>
 4 
 5 #include<cmath>
 6 
 7 #include<cstring>
 8 
 9 #include<algorithm>
10 
11 #include<iostream>
12 
13 #include<vector>
14 
15 #include<map>
16 
17 #include<set>
18 
19 #include<queue>
20 
21 #include<string>
22 
23 #define inf 1000000000
24 
25 #define maxn 100000+5
26 
27 #define maxm 500+100
28 
29 #define eps 1e-10
30 
31 #define ll long long
32 
33 #define pa pair<int,int>
34 
35 #define for0(i,n) for(int i=0;i<=(n);i++)
36 
37 #define for1(i,n) for(int i=1;i<=(n);i++)
38 
39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
40 
41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
42 
43 #define mod 1000000007
44 
45 using namespace std;
46 
47 inline int read()
48 
49 {
50 
51     int x=0,f=1;char ch=getchar();
52 
53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
54 
55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
56 
57     return x*f;
58 
59 }
60 int n,k,s,t,ans,a[maxn],b[maxn],l[maxn],r[maxn];
61 priority_queue<pa,vector<pa>,greater<pa> >q;
62 
63 int main()
64 
65 {
66 
67     freopen("input.txt","r",stdin);
68 
69     freopen("output.txt","w",stdout);
70 
71     t=read();k=read();
72     for1(i,t)a[i]=read();while(a[t]<=0)t--;
73     s=1;while(a[s]<=0)s++;
74     for(;s<=t;s++)if((a[s]>0&&a[s-1]>0)||(a[s]<=0&&a[s-1]<=0))b[n]+=a[s];else b[++n]=a[s];
75     for1(i,n)if(b[i]>0){ans+=b[i];k--;}else b[i]=-b[i];
76     if(k>=0){cout<<ans<<endl;return 0;}
77     for1(i,n)l[i]=i-1,r[i]=i+1,q.push(pa(b[i],i));
78     r[n]=0;
79     for1(i,abs(k))
80     {
81       while(b[q.top().second]!=q.top().first)q.pop();
82       int x=q.top().second;q.pop();
83       ans-=b[x];
84       if(!l[x]){b[r[x]]=inf;l[r[x]]=0;}
85       else if(!r[x]){b[l[x]]=inf;r[l[x]]=0;}
86       else 
87       {
88           b[x]=b[l[x]]+b[r[x]]-b[x];
89           b[l[x]]=b[r[x]]=inf;
90           r[l[x]=l[l[x]]]=l[r[x]=r[r[x]]]=x;
91           q.push(pa(b[x],x));
92       }
93     }
94     cout<<ans<<endl;
95 
96     return 0;
97 
98 } 
View Code

還有一點,之因此賦刪去的點的權值爲inf是爲了避免用手打堆,erase233

相關文章
相關標籤/搜索