最大M子段和 V2
51nod1053
這題還是我們熟悉的M子段和,只不過N,M<=50000。
這題似乎是一個堆+鏈表的題目啊
開始考慮把所有正數負數鎖在一起。
比如: 1 2 3 -1 –2 -3 666 縮成 6 -6 666這樣。
然后用一個堆來維護,就是說把所有的負數和正數都扔進堆里,先選所有正數,然后每一次把堆中絕對值最小的數(如果是負數且沒有左或右就跳過)和兩邊合并,鏈表維護一下。
當然實際實現用的是set…
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <limits> #include <set> #include <map> using namespace std; int n,m,l[233333],r[233333]; long long a[233333]; typedef pair<long long,int> pii; set<pii> ps; void del(int a) {int L=l[a],R=r[a];if(L) r[L]=R;if(R) l[R]=L; } int main() {int N;scanf("%d%d",&N,&m);long long ans=0,sum=0,ds=0;for(int i=1;i<=N;i++){int x;scanf("%d",&x);if((sum>0&&x<0)||(sum<0&&x>0)){a[++n]=sum;ds+=sum>0;ps.insert(pii(abs(sum),n));sum=0;}sum+=x;if(x>=0) ans+=x;}a[++n]=sum;ds+=sum>0;ps.insert(make_pair(abs(sum),n));for(int i=1;i<=n;i++) l[i]=i-1, r[i]=(i<n)?i+1:0;while(ds>m){int cur=ps.begin()->second;ps.erase(ps.begin());if((a[cur]<0&&(!l[cur]||!r[cur]))||!a[cur]) continue;ps.erase(pii(abs(a[l[cur]]),l[cur]));ps.erase(pii(abs(a[r[cur]]),r[cur]));ans-=abs(a[cur]);a[cur]+=a[l[cur]]+a[r[cur]];del(l[cur]); del(r[cur]);ps.insert(pii(abs(a[cur]),cur));--ds;}printf("%lld\n",ans); }轉載于:https://www.cnblogs.com/zzqsblog/p/5371371.html
總結
- 上一篇: 小宿舍管理程序
- 下一篇: memcpy实例(一)