1 条题解
-
1yejun LV 10 MOD @ 2019-01-08 21:02:40
/* 法一:运用优先队列简化代码 法二:若不熟悉STL,这里提供了手写堆 */ #define method_1 #ifdef method_1 /* 贪心 首先简化序列 将正负数合并 例如 2 2 -1 -3 2 -4 1 1 变成4 -4 2 -4 2 即变成正负数相间的形式 这时计算出正数的数量 若其小于等于m 答案就是正数的和 否则 就将其全部插入到优先队列里头(负数加绝对值之后插入) 每次取出小根堆的堆顶 将其删去 同时更新答案 其中 删去正数表示这个联通块不选 删去负数表示合并相邻两个联通块(若这个负数在两端 就直接删去 不更新答案) 最后为了维护删除后的序列 需要用一个简化的双向链表 */ #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<set> #include<map> #include<queue> #include<stack> #include<vector> #include<cstring> #include<cstdlib> using namespace std; typedef long long ll; const int maxn=1e5+5; const int INF=0x3f3f3f3f; ll n,m,a[maxn],mark[maxn],cnt=0,temp=0,ans=0,l[maxn],r[maxn]; priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q; void del(int x){ mark[x]=1; l[r[x]]=l[x]; r[l[x]]=r[x]; } int main() { ios::sync_with_stdio(false); cin>>n>>m; ll x; for(int i=1;i<=n;i++){ cin>>x; if(x!=0){ if(a[temp]*x>0) a[temp]+=x; else a[++temp]=x; } } n=temp; for(int i=1;i<=n;i++){ if(a[i]>0){ cnt++; ans+=a[i]; } l[i]=i-1; r[i]=i+1; q.push(make_pair(abs(a[i]),i)); } while(cnt>m){ while(mark[q.top().second]) q.pop(); int x=q.top().second; q.pop(); if((l[x]==0||r[x]==n+1)&&a[x]<0) del(x); //注意||的优先级低于&& 所以要有括号 else{ ans-=abs(a[x]); cnt--; a[x]+=a[l[x]]+a[r[x]]; q.push(make_pair(abs(a[x]),x)); del(l[x]); del(r[x]); } } cout<<ans; return 0; } #endif #ifdef method_2 /* */ #include<iostream> #include<cstdio> using namespace std; int a[100010],b[100010],L[100010],R[100010],q[100010],v[100010]; int n,m,t,p,ans,i,temp,x; void up(int p) { while(p>1) if(b[q[p]]<b[q[p>>1]]) { swap(q[p],q[p>>1]); swap(v[q[p]],v[q[p>>1]]); p>>=1; } else break; } void down(int l,int r) { int t=2*l; while(t<=r) { if(t<r&&b[q[t]]>b[q[t+1]]) t++; if(b[q[l]]>b[q[t]]) { swap(q[l],q[t]); swap(v[q[l]],v[q[t]]); l=t,t=2*l; } else break; } } void insert(int i) { q[++p]=i; v[i]=p; up(p); } void erase(int i) { v[q[p]]=v[i]; q[v[i]]=q[p]; p--; up(v[i]); down(v[i],p); } int main() { cin>>n>>t; for(i=1; i<=n; i++) scanf("%d",&a[i]); for(; n&&a[n]<=0; n--); for(i=1; i<=n&&a[i]<=0; i++); if(i>n) { puts("0"); return 0; } for(; i<=n; i++) if(a[i]>0&&a[i-1]>0 || a[i]<=0&&a[i-1]<=0) b[m]+=a[i]; else b[++m]=a[i]; for(i=1; i<=m; i++) if(b[i]>0) temp++,ans+=b[i]; else b[i]=-b[i]; if(temp<=t) { cout<<ans<<endl; return 0; } for(i=1; i<=m; i++) { L[i]=i-1,R[i-1]=i; insert(i); } for(i=t; i<temp; i++) { ans-=b[x=q[1]]; if(!L[x]) { erase(x),erase(R[x]); L[R[R[x]]]=0; } else if(!R[x]) { erase(x),erase(L[x]); R[L[L[x]]]=0; } else { erase(L[x]),erase(R[x]),erase(x); b[x]=b[L[x]]+b[R[x]]-b[x]; insert(x); L[x]=L[L[x]],R[L[x]]=x; R[x]=R[R[x]],L[R[x]]=x; } } cout<<ans<<endl; return 0; } #endif
- 1
信息
- 难度
- 7
- 分类
- (无)
- 标签
- (无)
- 递交数
- 55
- 已通过
- 9
- 通过率
- 16%
- 被复制
- 3
- 上传者