CF1465-D. Grime Zoo
CF1465-D. Grime Zoo
题意:
一个长度为n,由\(0,1,?\)这三个字符构成的字符串,字符串中\(01\)子串贡献\(x\)值,\(10\)的子串贡献\(y\)值,现在让你把\(?\)替换成\(0\)或\(1\),问你整个字符串的总贡献最少可以是多少?
子串是指可以通过删去字符串中的一些字符得到的字符串。不同的\(01\)或\(10\)子串只需要让他们其中的一个\(0\)或\(1\)来自字符串中不同的位置即可。
思路:
先说一个结论:当\(x<y\)的时候,无论两个\(?\)(后面分别称这两个\(?\)为\(c_l\)和\(c_r\))之间的的\(0\)和\(1\)的数量是多少、他们是如何排列的,\(c_l\)取\(0\),\(c_r\)取\(1\)的时候,这个字符串的总贡献一定小于\(c_l\)取\(1\),\(c_r\)取\(0\)的时候的总贡献,即\(w_{c_l=0,c_r=1}<w_{c_l=1,c_r=0}\)。反之\(x>y\)的时候也能得到类似的结论。
证明如下:
假设\(c_l\)和\(c_r\)之间有\(n_0\)个\(0\),\(n_1\)个\(1\),那么当\(c_l=0,c_r=1\)的时候,这段字符串的总贡献\(w_{c_l=0,c_r=1}=(1+n_1)*x+n_0*x+w=(1+n_0+n_1)*x+w\),其中\(w\)是\(c_l,c_r\)之间的字符产生的贡献;当\(c_l=1,c_r=0\)的时候,这段字符串的总贡献\(w_{c_l=1,c_r=0}=(1+n_0)*y+n_1*y+w=(1+n_0+n_1)*y+w\),那么\(w_{c_l=0,c_r=1}-w_{c_l=1,c+r=0}=(1+n_0+n_1)*(x-y)=(r-l)*(x-y)\)。
从上面的式子可以得出结论:\(x<y\)时,\(w_{c_l=0,c_r=1}<w_{c_l=1,c_r=0}\);\(x>y\)时,\(w_{c_l=0,c_r=1}>w_{c_l=1,c+r=0}\)。
这样就可以枚举字符串中的每个位置,将当前枚举的位置之前的所有\(?\)替换为\(1(或0)\),之后所有的\(?\)替换为\(0(或1)\),计算整个字符串的贡献,取最小的一个即可。
但是这样枚举,暴力计算总贡献,时间复杂度为\(O(n^3)\),所以可以通过前缀和进行优化:用前缀和分别维护前\(i\)个字符和后\((n-i+1)\)个字符中\(0\)和\(1\)的数量以及分别维护前\(i\)个字符和后\((n-i+1)\)个字符构成的字符串的总贡献,这样就可以将复杂度从\(O(n^3)\)降为\(O(n)\)。具体的计算方法及实现细节见代码及代码注释。
AC代码:
这段代码使用了一些小技巧,比如将\(x<y\)和\(x>y\)这两种情况归结为一种情况、前缀和的统计方式。具体的在代码以及代码注释中有所体现。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll;
const int Maxn = 100005;
const ll INF = 0x3f3f3f3f3f3f3f3f;
char s[Maxn];
int char_pre[Maxn], char_suf[Maxn]; // 前i个字符中1的数量,后i个字符中0的数量
ll cnt_pre[Maxn], cnt_suf[Maxn]; // 前i个字符构成的愤怒值,后i个字符构成的愤怒值
void solve() {
ll x, y;
scanf("%s %lld %lld", s + 1, &x, &y);
int n = strlen(s + 1);
if (x > y) { // 让01 > 10 的情况转化为 01 < 10的情况,这样把情况做了统一
std::swap(x, y);
for (int i = 1; i <= n; i++) {
if (s[i] == '1') {
s[i] = '0';
} else if (s[i] == '0') {
s[i] = '1';
}
}
}
for (int i = 1; i <= n; i++) {
if (s[i] == '1') {
// 这里之所以记录1的数量而不是0,是因为在x<y的时候'0'和'?'是被归到一类里面,这样容易统计
char_pre[i] = char_pre[i - 1] + 1;
cnt_pre[i] = cnt_pre[i - 1] + (i - char_pre[i]) * x;
} else { // 这里把'?'看作为0
char_pre[i] = char_pre[i - 1];
cnt_pre[i] = cnt_pre[i - 1] + char_pre[i - 1] * y;
}
}
for (int i = n; i > 0; i--) {
if (s[i] == '0') {
char_suf[i] = char_suf[i + 1] + 1;
cnt_suf[i] = cnt_suf[i + 1] + (n - i + 1 - char_suf[i]) * x;
} else { // 这里把'?'看作为1
char_suf[i] = char_suf[i + 1];
cnt_suf[i] = cnt_suf[i + 1] + char_suf[i] * y;
}
}
ll ans = INF;
for (int i = 0; i <= n; i++) {
// 枚举每个位置,如果这里的字符是'?'那么就会当作'0'处理(见34行)
// 注意这里的i最开始是从0开始的,而不是从1,是为了处理第一个字符为'?'的情况
ans = std::min(ans, cnt_pre[i] + cnt_suf[i + 1] +
1LL * char_pre[i] * char_suf[i + 1] * y +
1LL * (i - char_pre[i]) * (n - i - char_suf[i + 1]) * x);
/*
i以及i之前的字符构成的字符串(所有的?看作0)的总贡献 +
i之后的字符构成的字符串(所有的?看作1)的总贡献 +
i以及i之前的字符中1的数量(所有?看作0) * i之后的字符中0的数量(所有?看作1) +
i以及i之前的字符中0的数量(所有?看作0) * i之后的字符中1的数量(所有?看作1)
*/
}
printf("%lld\n", ans);
}
int main() {
solve();
return 0;
}
CF1465-D. Grime Zoo的更多相关文章
- zookeeper的zoo.cfg的配置
zookeeper的默认配置文件为zookeeper/conf/zoo_sample.cfg,需要将其修改为zoo.cfg.其中各配置项的含义,解释如下: tickTime:CS通信心跳时间 Zook ...
- (转)The Neural Network Zoo
转自:http://www.asimovinstitute.org/neural-network-zoo/ THE NEURAL NETWORK ZOO POSTED ON SEPTEMBER 14, ...
- Mininet建立topology zoo中的拓扑
以前用Mininet建立拓扑都是在别人的代码上进行需求上的修改,这次从头开始将topology zoo(http://www.topology-zoo.org/)中的拓扑用Mininet建立,不失一般 ...
- zoo.cfg配置
zookeeper的默认配置文件为zookeeper/conf/zoo_sample.cfg,需要将其修改为zoo.cfg.其中各配置项的含义,解释如下: 1.tickTime:CS通信心跳时间 Zo ...
- Codeforces Round #250 (Div. 1) B. The Child and Zoo 并查集
B. The Child and Zoo Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/438/ ...
- cf437D The Child and Zoo
D. The Child and Zoo time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- CF437D(The Child and Zoo)最小生成树
题目: D. The Child and Zoo time limit per test 2 seconds memory limit per test 256 megabytes input sta ...
- Codeforces 437D The Child and Zoo(贪心+并查集)
题目链接:Codeforces 437D The Child and Zoo 题目大意:小孩子去參观动物园,动物园分非常多个区,每一个区有若干种动物,拥有的动物种数作为该区的权值.然后有m条路,每条路 ...
- Codeforces 437 D. The Child and Zoo 并查集
题目链接:D. The Child and Zoo 题意: 题意比较难懂,是指给出n个点并给出这些点的权值,再给出m条边.每条边的权值为该条路连接的两个区中权值较小的一个.如果两个区没有直接连接,那么 ...
随机推荐
- 用percona monitoring plugins 监控mysql
下载:http://www.percona.com/redir/downloads/percona-monitoring-plugins/1.1.1/percona-zabbix-templates- ...
- 实现所有SAP设备打印机并行打印
SAP版本:ECC 6.0 701 1.如何实现所有SAP设备打印机并行打印? I.通过事务码:SPAD,进入假脱机管理初始屏幕.点击左上角的菜单中 配置(c)=>输出设备,进入SAP系统 输出 ...
- ALV中的分隔条(SPLITTER_CONTROL)
如上图,可以做成左右的分割,当然也可以做成上下的分割效果,在每个分割的容器内,显示各自的内容. 需要使用的class: cl_gui_splitter_container, cl_gui_custom ...
- Android根据pdf模板生成pdf文件
我们需要生成一些固定格式的pdf文件或者一些报表数据,那么我们可以用 iText包去做. 需要包含的jar包:iText-5.0.6.jar iTextAsian.jar ,怎样jar包导入工程 ...
- Nginx(七):location的使用以及nginx关闭原理
上一篇中,我们了解了如何nginx的配置原则及解析框架,以及解析location配置的具体实现,相信大家对该部分已经有了比较深刻的认识. 本篇,我们进一步来了解下,解析之后的配置,如何应用到实际中的吧 ...
- 2021最新WordPress安装教程(一):Centos7安装Apache
一转眼2020年已经过去了,看网络上很多WordPress的安装教程都比较旧,有些写的不太详细,WordPress是站长最喜欢的一款建站系统,数据统计到2020年为止,WordPress在所有网站的市 ...
- SpringMVC听课笔记(三:使用@RequestMapping映射请求)
1. Spring MVC使用 @RequestMapping 注解为控制器指定可以处理哪些URL请求 2. 标注点: --类定义处:提供初步的请求映射信息.相对于WEB应用的根目录 --方法处:提供 ...
- Vue3.0网页版聊天|Vue3.x+ElementPlus仿微信/QQ界面|vue3聊天实例
一.项目简介 基于vue3.x+vuex+vue-router+element-plus+v3layer+v3scroll等技术构建的仿微信web桌面端聊天实战项目Vue3-Webchat.基本上实现 ...
- SSM框架搭建详细解析
总结了一下搭建SSM框架流程,在以后用到的时候方便回头使用. 使用工具:MyEclipse 2015:Tomcat 8版本:jdk1.8版本. 首先: 1:创建一个WebProject项目,jdk1. ...
- Java8 ,LocalDate,LocalDateTime处理日期和时间工具类,
Java8 ,LocalDate,LocalDateTime处理日期和时间工具类 1.获取今天的日期 2.在Java 8 中获取年.月.日信息 3.在Java 8 中处理特定日期 4.在Java 8 ...