首页IT科技p0700变速箱控制系统(CF1779C Least Prefix Sum 题解)

p0700变速箱控制系统(CF1779C Least Prefix Sum 题解)

时间2025-09-16 07:47:44分类IT科技浏览4950
导读:CF链接:Least Prefix Sum Luogu链接:...

CF链接:Least Prefix Sum

Luogu链接:LeastPrefix Sum

$ {\scr \color {CornflowerBlue}{\text{Solution}}} $

先来解释一下题意:

给定一个数组               ,问最少把多少个数变成相反数                       ,使得$ \forall \cal{i}$,$ \sum_{k=1}^i a_k$ $ \le$$\sum_{k=1}^m a_k$

发现对于所有数据点       ,$ \cal{n} \le 2 \times 10^5$       ,说明需要 $ Ο(\cal{n \log n}) $ 或者 $ O(\cal{n}) $的算法               。

分析一下题目                       ,发现要分成$ \cal{i} > \cal{m}$ 与$ \cal{i} < \cal{m}$两种情况分类讨论

当 $\cal{i}$ $ > \cal{m}$时:

什么时候才能使$\sum_{k=1}^i a_k$ $ \le$$\sum_{k=1}^m a_k$ 成立呢?

是不是只要使新加的每一段都小于等于0就行了?($\sum_{k=m}^i a_k$ $ \le$$ 0$)

也很好证明:一个数($\sum_{k=1}^m a_k$)加上一个小于等于0的数($\sum_{k={m+1}}^i a_k$)               ,一定不大于原数                      。

当 $\cal{i}$ $ < \cal{m}$时:

同理       ,只要使后加的每一段都小于等于0就行了($\sum_{k=i}^i a_k$ $ \ge$$ 0$)

也很好证明:一个数($\sum_{k=1}^i a_k$)加上一个大于等于0的数($\sum_{k=i}^m a_k$)                      ,一定不小于原数        。

而且               ,由于这两种情况类似(博主太懒),那就只考虑当 $\cal{i}$ $ > \cal{m}$的情况吧               。

问题已经转化完了                      ,接下来怎么办?

第一眼想到的是贪心                      。

设当前要取第$\cal{i}$个        。

有一个不成熟的贪心:如果目前累加和加上$a_i$还是小于等于$0$的                      ,就加上$a_i$,如果大于$0$了               ,就把$a_i$取反                      ,$ ans+1$       。

Hack数据

我们只要把999 变成-999就行了       ,但如果按上面贪心方法               ,我们要把2                       ,3都改变!

那么贪心就不可以用了吗?

有个神奇的东西交叫反悔贪心!

简单说一下:对于当前不是最优的情况       ,留到后面重新选择                      。

我们肯定要让每次改变值后       ,获得综合最小的值                       ,但当前的选择又不一定最有优               。

我们可以用一个优先队列维护               ,到了每次要改的时候       ,从优先队列中选出一个收益最大(使目前累加和最大或最小)的值修改       。

注意开$ \cal{long long}$并且清空优先队列!

Code(赛时代码                      ,过丑见谅QwQ):

#include<bits/stdc++.h> #define L long long using namespace std; L a[200005]; priority_queue<L,vector<L>,greater<L> > q; int main() { int t; scanf("%d",&t); while(t--) { while(!q.empty()) q.pop(); int n,m,ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); if(n==1) { printf("0\n"); continue; } if(m==1) { L mu=0; for(int i=m+1;i<=n;i++) { if(a[i]>=0) mu+=a[i]; else if(a[i]<0 && mu+a[i]>=0) { q.push(a[i]); mu+=a[i]; } else { ans++; q.push(a[i]); mu+=a[i]; mu-=2*q.top(); q.pop(); } } printf("%d\n",ans); continue; } L mu=0; for(int i=m+1;i<=n;i++) { if(a[i]>=0) mu+=a[i]; else if(a[i]<0 && mu+a[i]>=0) { q.push(a[i]); mu+=a[i]; } else { ans++; q.push(a[i]); mu+=a[i]; mu-=2*q.top(); q.pop(); } } while(!q.empty()) q.pop(); mu=0; for(int i=m;i>=2;i--) { if(a[i]<=0) mu+=a[i]; else if(a[i]>0 && mu+a[i]<=0) { q.push(-a[i]); mu+=a[i]; } else { ans++; q.push(-a[i]); mu+=a[i]; mu+=2*q.top(); q.pop(); } } printf("%d\n",ans); } return 0; }
声明:本站所有文章               ,如无特殊说明或标注,均为本站原创发布                      。任何个人或组织                      ,在未征得本站同意时                      ,禁止复制               、盗用                      、采集        、发布本站内容到任何网站               、书籍等各类媒体平台               。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
偃师网站建设(偃师市百度) spring声明式事务配置代码(学习笔记——Spring声明式事务管理;Spring中支持事务管理;使用声明式事务管理;Spring声明式事务管理属性)