【BZOJ 2288】 2288: 【POJ Challenge】生日礼物 (贪心+优先队列+双向链表)
2288: 【POJ Challenge】生日礼物
Description
ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, ..., AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物。
自然地,ftiasch想要知道选择元素之和的最大值。你能帮助她吗?
Input
第1行,两个整数 N (1 ≤ N ≤ 105) 和 M (0 ≤ M ≤ 105), 序列的长度和可以选择的部分。
第2行, N 个整数 A1, A2, ..., 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 }
给一个sample in: 5 53 -20 3 -27 68 out: 77
发发表情更健康
2017-01-14 11:01:57