P2882 Face The Right Way G 题解
题目
Farmer John has arranged his N \((1 ≤ N ≤ 5,000)\) cows in a row and many of them are facing forward, like good cows. Some of them are facing backward, though, and he needs them all to face forward to make his life perfect.
Fortunately, FJ recently bought an automatic cow turning machine. Since he purchased the discount model, it must be irrevocably preset to turn K \((1 ≤ K ≤ N)\) cows at once, and it can only turn cows that are all standing next to each other in line. Each time the machine is used, it reverses the facing direction of a contiguous group of K cows in the line (one cannot use it on fewer than K cows, e.g., at the either end of the line of cows). Each cow remains in the same location as before, but ends up facing the opposite direction. A cow that starts out facing forward will be turned backward by the machine and vice-versa.
Because FJ must pick a single, never-changing value of K, please help him determine the minimum value of K that minimizes the number of operations required by the machine to make all the cows face forward. Also determine M, the minimum number of machine operations required to get all the cows facing forward using that value of K.
N头牛排成一列\(1<=N<=5000\)。每头牛或者向前或者向后。为了让所有牛都 面向前方,农夫每次可以将K头连续的牛转向\(1<=K<=N\),求操作的最少次数M和对应的最小K。
输入格式
Line 1: A single integer: \(N\)
Lines \(2..N+1\): Line \(i+1\) contains a single character, F or B, indicating whether cow \(i\) is facing forward or backward.
第一行一个整数N
第2行至\(N+1\)行是一个字符,F或B,表示向前或向后.
输出格式
Line 1: Two space-separated integers: \(K\) and \(M\)
一行两个数字,\(K\)和\(M\)
输入样例
7
B
B
F
B
F
B
B
输出样例
3 3
题解
很容易想到暴力解法,三层循环,一层枚举\(k\),一层遍历从前往后遍历数组,一遇到向后的牛就一层循环反转后面长度为k的数组,时间复杂度\(O(n^3)\),显然不行,那么就需要优化.
看最后一层循环,可以使用差分优化,每次反转就将次数+1,由于反转两次相当于没有反转,所以就可以根据次数和原本的状态推出反转后的状态.
不需要开一个前缀和数组,因为从前往后遍历,只需要定义一个sum
变量存储前缀和,一边累计前缀和一边修改差分数组即可.
代码
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 5010, INF = 1e9;
int n, r, a[maxn], f[maxn];
int check(int k) {
memset(f, 0, sizeof(f));
int sum = 0, ans = 0;
for (int i = 1; i <= n; ++i) {
if (~(a[i] + sum) & 1) { // 如果 a[i] + flag 为偶数
if (i + k - 1 > n) return INF + 1; //超过限制, 返回最大值以保证答案不更新
f[i] ++, f[i + k - 1] --, ans++;
}
sum += f[i];
}
return ans;
}
int main() {
scanf("%d", &n);
char status;
for (int i = 1; i <= n; i++) getchar(), a[i] = getchar() == 'B' ? 0 : 1;
int maxv = INF, ansk = n;
for (int k = 1; k <= n; k++) if ((r = check(k)) <= maxv) maxv = r, ansk = k;
printf("%d %d\n", ansk, maxv);
return 0;
}
附
又到了水的时间
介绍一些我觉得有意思的小技巧,可以让你的代码看起来更简洁难懂
- 判断一个数字奇偶
正常操作自然是模2看结果是0还是1,但是你是否感觉加一个==0
或==1
太累赘呢?如果想要a
为奇数时表达式为真,可以直接使用a%2
.如果想要偶数时表达式为真,可以使用!(a%2)
.
但是后面这个这个又不美观了,要知道if
,while
等语句的条件也是要加括号的,如果想要偶数时表达式为真,代码可能会变成这样:
if(!(a%2)){
//do something
}
双层括号套一起,太丑了,这时候建议使用位运算,我们要知道一个整数为奇数时,其二进制表示最低位为1,反之为0,那么对这个整数与1取最低位,就可以判断奇偶
如果想要a
为奇数时表达式为真,可以使用a&1
.如果想要偶数时表达式为真,可以使用~a&1
同样是上面那种情况
if(~a&1){
//do something
}
看起来是不是更清爽让人看不懂了呢?
- 合理使用
getchar()
由于scanf
和cin
的返回值不是输入值,所以不能直接放在条件表达式里,但是getchar()
却不一样,像这种输入字符表示状态的题,可以使用getchar()
来获取输入
getchar(), a[i] = getchar() == 'B' ? 0 : 1;
第一个getchar()是读取回车符,然后用三元运算符判断输入,B为0,F为1
- 当条件表达式和语句块内都使用函数返回值
由于当更新答案时,还要执行其它操作,不能用max
,min
函数,所以需要使用if语句
这里的情况就是
int r=check(k);
if (r <= maxv) maxv = r, ansk = k;
第一行看起来就不爽,想干掉它,但是如果改成:
if (check(k) <= maxv) maxv = check(k), ansk = k;
调用两次函数浪费了时间显然不能选
这时候注意,赋值语句也是有返回值的!其实也能算表达式?
所以你可以这么写(r变量先定义好):
if ((r = check(k)) <= maxv) maxv = r, ansk = k;
P2882 Face The Right Way G 题解的更多相关文章
- 洛谷P3104 Counting Friends G 题解
题目 [USACO14MAR]Counting Friends G 题解 这道题我们可以将 \((n+1)\) 个边依次去掉,然后分别判断去掉后是否能满足.注意到一点, \(n\) 个奶牛的朋友之和必 ...
- 洛谷P2115 Sabotage G 题解
题目 [USACO14MAR]Sabotage G 题解 本蒟蒻又来了,这道题可以用二分答案来解决.我们可以设答案最小平均产奶量为 \(x \ (x \in[1,10000])\) .然后二分搜索 \ ...
- Hdoj 2454.Degree Sequence of Graph G 题解
Problem Description Wang Haiyang is a strong and optimistic Chinese youngster. Although born and bro ...
- P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G 题解
原题链接 POJ的链接 简要题意: 给定一张图,求多少个点,每个点都能到达它. 本题作为强连通分量的入门题. 何为强连通分量?有什么用? 下面一一解释. 首先,我们要确认,这道题目如果不用强连通分量而 ...
- USACO07NOV Cow Relays G 题解
题目 For their physical fitness program, \(N (2 ≤ N ≤ 1,000,000)\) cows have decided to run a relay ra ...
- Codeforces Round #677 (Div. 3) E、G题解
E. Two Round Dances #圆排列 题目链接 题意 \(n\)(保证偶数)个人,要表演一个节目,这个节目包含两种圆形舞蹈,而每种圆形舞蹈恰好需要\(n/2\)个人,每个人只能跳一种圆形舞 ...
- 2018年第九届蓝桥杯【C++省赛B组】B、C、D、F、G 题解
B. 明码 #STL 题意 把每个字节转为2进制表示,1表示墨迹,0表示底色.每行2个字节,一共16行,布局是: 第1字节,第2字节 第3字节,第4字节 .... 第31字节, 第32字节 给定一段由 ...
- [NOI2009] 诗人小G [题解]
诗人小G 题目大意 给出 \(n\) 个长度不超过 \(30\) 的句子,要求你对其进行排版. 对于每一行,有一个规定的行标准长度 \(L\) ,每一行的不协调度等于该行的实际长度与行标准长度差的绝对 ...
- FJUT寒假作业第二周G题解快速幂
题目来源:http://210.34.193.66:8080/vj/Contest.jsp?cid=161#P6 题意:求n个数字的乘积对c取摸.主要就是有快速幂扩展到广义幂的过程. 首先题目 ...
随机推荐
- Python:求时间差(天时分秒格式)
传入一个时间戳,以天时分秒格式打印出时间差 输入一个10位的时间戳,求出时间差 def time_diff(timestamp): onlineTime = datetime.datetime.fro ...
- 关于virgo-tomcat-server-3.6.0.RELEASE服务的启动
1.先查看程序是否启动,如果已经启动可以执行第3步的操作进行关闭. [user01@ ~]$ # ps -ef|grep java //查看virgo-tomcat-server的java进程是否存在 ...
- GIT 仓库的搭建
1.安装并配置必要的依赖关系 在CentOS 7(和RedHat / Oracle / Scientific Linux 7)上,以下命令还将在系统防火墙中打开HTTP和SSH访问. yum inst ...
- HTML5 3D 粒子波浪动画特效DEMO演示
需要thress.js插件: http://github.com/mrdoob/three.js // three.js - http://github.com/mrdoob/three.js ...
- 【JAVA进阶架构师指南】之五:JVM性能调优
前言 首先给大家说声对不起,最近属实太忙了,白天上班,晚上加班,回家还要收拾家里,基本每天做完所有事儿都是凌晨一两点了,没有精力再搞其他的了. 好了,进入正题,让我们来聊聊JVM篇最后一个章节 ...
- nodejs 换源
解决npm install安装慢的问题国外镜像会很慢 可用 get命令查看registry npm config get registry 原版结果为 http://registry.npmjs.or ...
- 果然学习好是有道理的,学习Mysql与正则表达式笔记
正则表达式是用来匹配文本的特殊的字符集合,将一个正则表达式与文本串进行比较,Mysql中用where子句提供支持,正则表达式关键字:regexp1.使用‘|’匹配两个串中的一个 2.使用‘[]’匹配几 ...
- Python进阶——详解元类,metaclass的原理和用法
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题第18篇文章,我们来继续聊聊Python当中的元类. 在上上篇文章当中我们介绍了type元类的用法,在上一篇文章当中我 ...
- C#中的闭包和意想不到的坑
虽然闭包主要是函数式编程的玩意儿,而C#的最主要特征是面向对象,但是利用委托或lambda表达式,C#也可以写出具有函数式编程风味的代码.同样的,使用委托或者lambda表达式,也可以在C#中使用闭包 ...
- 性能测试之JVM的故障分析工具VisualVM
VisualVM 是随JDK一同发布的jvm诊断工具,通过插件可以扩展很多功能,插件扩展也是其精华所在. 提供了一个可视界面,用于在Java应用程序在Java虚拟机上运行时查看有关Java应用程序的详 ...