[关闭]
@yang12138 2018-12-03T14:53:52.000000Z 字数 2149 阅读 1031

最大M子段和

未分类


题目链接:http://www.51nod.com/Challenge/Problem.html#!#problemId=1053

长度为的整数数列,最多取个不相交子段求和,问和最大是多少?

先把数列中所有去掉,然后把相邻的同号的加起来,这时数列的相邻两个数肯定不同号。对于处理后的数组,把所有正数加到里,设正数的个数有个,如果,那么答案就是,如果,设

每次取出数列中绝对值最小的数,如果是负数,则视为将其左右两块正数合并,代价是;如果是正数,则视为将这块舍掉,然后和左右两块负数合并,代价也是。重复进行次。

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <string>
  6. #include <math.h>
  7. #include <cstdlib>
  8. #include <set>
  9. using namespace std;
  10. typedef long long ll;
  11. typedef pair<ll,int>pii;
  12. const int N=1e5+10;
  13. ll a[N];
  14. int l[N],r[N];
  15. struct Node{
  16. ll val;
  17. int id;
  18. Node(){}
  19. Node(ll val,int id):val(val),id(id){}
  20. bool operator < (const Node& tmp)const{
  21. return pii(abs(val),id)<pii(abs(tmp.val),tmp.id);
  22. }
  23. };
  24. void del(int i){
  25. l[r[i]]=l[i];
  26. r[l[i]]=r[i];
  27. }
  28. const int BS = 1e7;
  29. char buf[BS];
  30. char *head,*tail;
  31. int flag=0;
  32. char getch(){
  33. if(head==tail){
  34. int len = fread(buf,1,BS,stdin);
  35. tail = (head = buf)+len;
  36. flag++;
  37. if(flag>=2) exit(0);
  38. }
  39. return *head++;
  40. }
  41. template<typename T>
  42. void scan(T& x){
  43. x=0;
  44. char ch=getch();
  45. while(!(ch=='-' || (ch>='0' && ch<='9'))) ch=getch();
  46. bool flag=0;
  47. if(ch=='-') flag=1,ch=getch();
  48. while(ch>='0' && ch<='9') x=10*x+ch-'0',ch=getch();
  49. if(flag) x=-x;
  50. }
  51. void solve(){
  52. int n,tot;
  53. scan(n),scan(tot);
  54. for(int i=1;i<=n;i++) scan(a[i]);
  55. int m=0;
  56. for(int i=1;i<=n;i++) if(a[i]!=0) a[++m]=a[i];
  57. n=m,m=0;
  58. for(int i=1;i<=n;){
  59. int j=i;
  60. while(j+1<=n && 1LL*a[j+1]*a[j]>0) j++;
  61. ll tmp=0;
  62. for(int k=i;k<=j;k++) tmp+=a[k];
  63. i=j+1,a[++m]=tmp;
  64. }
  65. n=m;
  66. for(int i=0;i<=n;i++) r[i]=i+1;
  67. for(int i=1;i<=n+1;i++) l[i]=i-1;
  68. set<Node>st;
  69. for(int i=1;i<=n;i++){
  70. st.insert(Node(a[i],i));
  71. if(a[i]>0) tot--;
  72. }
  73. ll ans=0;
  74. for(int i=1;i<=n;i++) if(a[i]>0) ans+=a[i];
  75. tot=-tot;
  76. while(tot>0){
  77. Node u = *st.begin();
  78. st.erase(u);
  79. if(u.val==0) continue;
  80. if(u.val<0){
  81. if(l[u.id]==0 || r[u.id]>n) continue;
  82. ans-=abs(u.val);
  83. ll tval=u.val + a[l[u.id]] + a[r[u.id]];
  84. a[u.id]=tval;
  85. st.erase(Node(a[l[u.id]],l[u.id]));
  86. st.erase(Node(a[r[u.id]],r[u.id]));
  87. del(l[u.id]);
  88. del(r[u.id]);
  89. st.insert(Node(a[u.id],u.id));
  90. }
  91. else{
  92. ans-=abs(u.val);
  93. ll tval=u.val;
  94. if(l[u.id]!=0){
  95. tval += a[l[u.id]];
  96. st.erase(Node(a[l[u.id]],l[u.id]));
  97. del(l[u.id]);
  98. }
  99. if(r[u.id]<=n){
  100. tval += a[r[u.id]];
  101. st.erase(Node(a[r[u.id]],r[u.id]));
  102. del(r[u.id]);
  103. }
  104. a[u.id]=tval;
  105. st.insert(Node(a[u.id],u.id));
  106. }
  107. tot--;
  108. }
  109. cout<<ans<<endl;
  110. }
  111. int main(){
  112. while(1) solve();
  113. return 0;
  114. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注