当前位置: 首页 > news >正文

CF182C Optimal Sum

题目传送门

贪心、权值线段树

题意

给定一个数字 \(len\) 和一个长度为 \(n(n\le 10^5)\) 的数组 \(a\),你最多可以执行 \(k\) 次操作 \(a_i \leftarrow -a_i\),请你最大化

\[\max \limits_{i\in [1,n]} \bigl | \sum_{j=0}^{j=len-1} a_{i+j} \bigr | \]

题解

我们只有两种方向:让绝对值里东西尽可能小或者尽可能大,因此我们只有两种选择,选 \(k\) 个最小或最大的数反转。

我们通过一遍扫描过去统计答案,每次会有单点修改,现在我们要找一个可以维护区间前 \(k\) 大的数据结构,支持单点修改。

这里容易想到用离散化加权值线段树的方法,相当于一个桶,维护权值为 \(x\) 的数的个数和权值区间和。

这里可以用结构体开两颗一模一样的线段树,一个只存正数,一个只存负数。时间复杂度 \(O(n \log n)\)

代码

#include <bits/stdc++.h>
#define int long long using namespace std;
const int N=1e5+5;int n,len,k;
struct node{int val,sgn,id;
}a[N]; 
int w[N],tot;struct SegTree{#define ls k<<1#define rs k<<1|1 #define mid (l+r>>1)int sum[N<<2],cnt[N<<2];inline void pushup(int k){sum[k]=sum[ls]+sum[rs];cnt[k]=cnt[ls]+cnt[rs];}void add(int k,int l,int r,const int& x){if(l==r){sum[k]+=w[x];cnt[k]++;return;}if(x<=mid) add(ls,l,mid,x);else add(rs,mid+1,r,x);pushup(k);}void del(int k,int l,int r,const int& x){if(l==r){sum[k]-=w[x];cnt[k]--;return;}if(x<=mid) del(ls,l,mid,x);else del(rs,mid+1,r,x);pushup(k);}int query(int k,int l,int r,int x){if(!x) return 0;if(l==r) return w[l]*min(x,cnt[k]);if(cnt[rs]>=x) return query(rs,mid+1,r,x);return sum[rs]+query(ls,l,mid,x-cnt[rs]);}#undef ls #undef rs#undef mid
}tr[2];signed main(){cin.tie(nullptr)->sync_with_stdio(false);cin>>n>>len;for(int i=1;i<=n;i++){cin>>a[i].val;if(a[i].val<0) a[i].sgn=-1;else a[i].sgn=1;a[i].val=abs(a[i].val);w[++tot]=a[i].val;}cin>>k;sort(w+1,w+tot+1);tot=unique(w+1,w+tot+1)-w-1;for(int i=1;i<=n;i++) a[i].id=lower_bound(w+1,w+tot+1,a[i].val)-w;int s0=0,s1=0;for(int i=1;i<=len;i++){if(a[i].sgn==1) s0+=a[i].val,tr[0].add(1,1,tot,a[i].id);else s1+=a[i].val,tr[1].add(1,1,tot,a[i].id);}int ans=max(2*tr[0].query(1,1,tot,k)+s1-s0,2*tr[1].query(1,1,tot,k)+s0-s1);for(int i=2;i+len-1<=n;i++){if(a[i-1].sgn==1) tr[0].del(1,1,tot,a[i-1].id),s0-=a[i-1].val;else 			  tr[1].del(1,1,tot,a[i-1].id),s1-=a[i-1].val;if(a[i+len-1].sgn==1) tr[0].add(1,1,tot,a[i+len-1].id),s0+=a[i+len-1].val;else				  tr[1].add(1,1,tot,a[i+len-1].id),s1+=a[i+len-1].val;ans=max({ans,max(2*tr[0].query(1,1,tot,k)+s1-s0,2*tr[1].query(1,1,tot,k)+s0-s1)});}cout<<ans;return 0;
}
http://www.rkmt.cn/news/8180.html

相关文章:

  • HTB UNIV CTF 24 Armaxix靶场漏洞链:命令注入与账户接管实战
  • PyTorch Weight Decay 技术指南
  • js获取浏览器语言,以及调用谷歌翻译api翻译成相应的内容
  • The 2025 ICPC Asia EC Regionals Online Contest (II)
  • C++线上练习
  • 深入解析:N32G43x Flash 驱动移植与封装实践
  • 深入解析:uv:用 Rust 重写的极速 Python 包管理器
  • Caused by: java.lang.ClassNotFoundException: org.apache.rocketmq.remoting.common.RemotingUtil
  • VAE In JAX【个人记录向】
  • 057-Web攻防-SSRFDemo源码Gopher项目等
  • 060-WEB攻防-PHP反序列化POP链构造魔术方法流程漏洞触发条件属性修改
  • 059-Web攻防-XXE安全DTD实体复现源码等
  • 061-WEB攻防-PHP反序列化原生类TIPSCVE绕过漏洞属性类型特征
  • 049-WEB攻防-文件上传存储安全OSS对象分站解析安全解码还原目录执行
  • 云原生周刊:MetalBear 融资、Chaos Mesh 漏洞、Dapr 1.16 与 AI 平台新趋势
  • 045-WEB攻防-PHP应用SQL二次注入堆叠执行DNS带外功能点黑白盒条件-cnblog
  • 用 Kotlin 实现英文数字验证码识别
  • 语音芯片怎样挑选?语音芯片关键选型要点?
  • KingbaseES Schema权限及空间限额
  • UM2003A 一款 200 ~ 960MHz ASK/OOK +18dBm 发射功率的单发射芯片
  • HTTP库开发实战:核心库与httpplus扩展库示例解析
  • 用 Python 和 Tesseract 实现英文数字验证码识别
  • 禅道以及bug
  • 工业交换机调试的实用技巧与注意事项:提升网络稳定性与性能 - 实践
  • 第一次参与开源的时序数据库 IoTDB Committer:这份成就感是无可替代的
  • ECT-OS-JiuHuaShan 框架元推理的意义、价值、作用、应用场景和哲学理念的充分阐述:AGI奇点
  • mysql区分大小写吗,你可能忽略了这些关键细节
  • route-link 和 a 的区别
  • 实用指南:前端Form表单提交后跳转到指定页面
  • np.clip的使用