「KDOI-06-S」消除序列 题解

news/2024/9/27 12:18:00

分享一个应该很少人想到的做法。

首先贪心地想,第一种操作肯定最多选择一次。比如如果选择了下标 \(i\)\(j\) 进行第一种操作,那么就等价于在 \(\max\{i,j\}\) 进行了一次操作。由于代价是非负数,则我们最多只用执行一次。当然也可以不使用这种操作

有了这个思路,我们先考虑不使用第一种操作的最优答案,很明显就是 \(\begin{aligned} \sum _{i \notin P}b_i\end{aligned}\)

接着再考虑使用一次的情况。我们先假定在位置 \(j\) 处进行一次第一种操作,这就表示 \([1,j]\) 的所有数字都变成了 \(0\),我们将 \(i\in P \wedge i\in [1,j]\) 的所有 \(i\) 统计到集合 \(A\) 中,将 \(i \notin P \wedge i \notin [1,j]\) 的所有 \(i\) 统计到集合 \(B\) 中。这个时候不难发现 \(A\) 中的元素都是应当为 \(1\) 但是因为在 \(j\) 进行了第一种操作后变成 \(0\) 的下标,那么我们就要把它们全部再变为 \(1\);而在 \(B\) 中的元素则是不应当为 \(1\) 但是还保持初始状态 \(1\) 的下标,我们需要一个一个地将它们变为 \(0\)。则此时答案就是:

\[\begin{aligned}\min\{a_j+(\sum_{i\in A}c_i)+(\sum _{i\in B}b_i) \}\end{aligned} \]

但是数据范围不允许我们枚举 \(j\)。其实我们不难发现当 \(j\in [p_i,p_{i+1}-1]\)\(A\)\(B\) 两个集合是不变的。则代入上述式子唯一改变的就是 \(a_j\) 的值。而且题目中提到 \(\sum m\leq 5\times 10^5\),这说明 \(|A|\) 会很小,但是 \(|B|\) 有可能会很大,因此我们提前预处理出 \(\begin{aligned}sum_i=\sum _{k=1}^ib_k \end{aligned}\),则 \(\begin{aligned} \sum_{i\in B}b_i=sum_n-sum_j-num \end{aligned}\),其中 \(\begin{aligned}num=\sum_{k\in P\wedge k\in [j+1,n]}b_k\end{aligned}\)\(num\) 可以一步一步推得,因此计算量相对减少了很多。我们再代入进原式:

\[\min\{a_j+(\sum_{i\in A}c_i)+sum_n-sum_j-num\} \]

考虑到当前 \(j\) 枚举的区间保证 \(A\)\(B\) 不变,转换一下得到:

\[\min\{a_j-sum_j\}+(\sum_{i\in A}c_i)-num+sum_n \]

不难发现 \(\min\{a_j-sum_j\}\) 中的 \(a_j\)\(sum_j\) 都不会被修改,因此我们可以用 ST 表记录 \(a_j-sum_j\) 的最小值。然后我们就可以在规定的数据范围内通过了。

代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=5e5+5;
int n,m,q;
int p[MAXN];
int a[MAXN],b[MAXN],c[MAXN];
int sum[MAXN],st[MAXN][20];
int lg[MAXN];
int query(int l,int r)
{int k=lg[r-l+1];return min(st[l][k],st[r-(1<<k)+1][k]);
}
void read(int &x)
{x=0;short flag=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')	flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x*=flag;
}
signed main()
{read(n);for(int i=2;i<=n;i++)	lg[i]=lg[i>>1]+1;for(int i=1;i<=n;i++){for(int j=0;j<20;j++)	st[i][j]=1e15;}for(int i=1;i<=n;i++)	read(a[i]);for(int i=1;i<=n;i++)	read(b[i]),sum[i]=sum[i-1]+b[i];for(int i=1;i<=n;i++)	read(c[i]);for(int i=1;i<=n;i++)	st[i][0]=a[i]-sum[i];for(int j=1;j<=19;j++){for(int i=1;i+(1<<j)-1<=n;i++)	st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);}read(q);while(q--){read(m),p[m+1]=n+1;for(int i=1;i<=m;i++)	read(p[i]);int minn=sum[n],num=0,rsum=0,minx=n+1;for(int i=1;i<=m;i++)	minn-=b[p[i]],rsum+=b[p[i]],minx=min(minx,p[i]);if(minx>1)	minn=min(minn,query(1,minx-1)+sum[n]-rsum);for(int i=1;i<=m;i++)	num+=c[p[i]],rsum-=b[p[i]],minn=min(minn,query(p[i],p[i+1]-1)+sum[n]+num-rsum);cout<<minn<<endl;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/65361.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

「TAOI-2」Ciallo~(∠・ω )⌒★ 题解

手玩了一个小时终于做出来了,这不得写一篇题解记录一下?? 下面设 \(s\) 的长度为 \(n\),\(t\) 的长度为 \(m\)。 考虑分类讨论: 如果 \(s\) 中有一个子串 \(s\) 与 \(t\) 完全相同(可以用哈希进行比较),设 \(s\) 是 \(s\) 的第 \(l\) 到第 \(r\) 个字符组成的字符串,则…

伯俊开发回忆录---VIP充值退款增加短信验证逻辑

一、前提总部财务需要增加对VIP卡充值退款的管控,防止资金被异常盗用, 1、针对VIP充值退款获取验证码,表单增加验证码字段 2、系统随机生成6位数验证码并生成提醒信息通过公司发送平台进行发送 三、校验规则未输入验证码不允许提交 验证码校验不通过提示重新输入

我的博客生涯开始了

我的博客生涯开始了

渗透测试入门

什么是渗透测试? 定义: 渗透测试完全模拟黑客可能使用的攻击技术和漏洞发现技术,对目标系统的安全做深入的探测,发现系统最脆弱的环节,以期发现和挖掘系统中存在的漏洞,然后输出渗透测试报告,并提交给网络所有者。网络所有者根据渗透人员提供的渗透测试报告,可以清晰知…

常间的css样式问题处理

flex导致文字省略失效 单独使用文字省略,按预期工作: 给元素加上flex,文字省略失效: 解决方案:flex和文字省略不要放到一个元素上。 flex布局中,文字溢出省略不生效的问题 问题展示.container {display: flex;width: 400px;border: 1px solid #000; }.content {flex: 1; …

Spring上传文件乱码问题(问号版)

Spring上传文件乱码问题(问号版) 目录Spring上传文件乱码问题(问号版)一、问题描述:二、原因分析三、解决办法 一、问题描述: spring项目上传文件,后端接收文件并获取文件名称,名称中文变成 “?”,例如:??abc()??.xml,其中问号为中文字符 // 前端传递参数 Mult…

伯俊开发回忆录---云POS待办事项增加稽核通知功能

一、事件前景总部财务稽核通知下发流程: 1.整理EXECL通知督导, 2.督导通知对应的门店, 3.收集完反馈意见汇报给分区财务审核 4.分区财务审核之后再通知总部财务审核, 这样整个稽核流程以及周期将大大影响稽核效率,因此希望在云POS门店端直接增加待办事项减少中间沟通环节。…

我,一个小白,居然用 AI 工具修改了公司前端代码!

背景 有一天同事发现公司网站的某个页面上有三个 H1 标签,懂行的都知道,有三个 H1 标签虽然不会对网站的访问产生影响,但是对于搜索引擎来讲,就比较麻烦了,因为一般搜索引擎都是靠 H1 标签、TDK 等来对网页的内容进行抓取,然后再进行质量优劣的判断。三个 H1 标签,搜索引…