题目

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;
}

又到了水的时间

介绍一些我觉得有意思的小技巧,可以让你的代码看起来更简洁难懂

  1. 判断一个数字奇偶

正常操作自然是模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
}

看起来是不是更清爽让人看不懂了呢?

  1. 合理使用getchar()

由于scanfcin的返回值不是输入值,所以不能直接放在条件表达式里,但是getchar()却不一样,像这种输入字符表示状态的题,可以使用getchar()来获取输入

getchar(), a[i] = getchar() == 'B' ? 0 : 1;

第一个getchar()是读取回车符,然后用三元运算符判断输入,B为0,F为1

  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 题解的更多相关文章

  1. 洛谷P3104 Counting Friends G 题解

    题目 [USACO14MAR]Counting Friends G 题解 这道题我们可以将 \((n+1)\) 个边依次去掉,然后分别判断去掉后是否能满足.注意到一点, \(n\) 个奶牛的朋友之和必 ...

  2. 洛谷P2115 Sabotage G 题解

    题目 [USACO14MAR]Sabotage G 题解 本蒟蒻又来了,这道题可以用二分答案来解决.我们可以设答案最小平均产奶量为 \(x \ (x \in[1,10000])\) .然后二分搜索 \ ...

  3. Hdoj 2454.Degree Sequence of Graph G 题解

    Problem Description Wang Haiyang is a strong and optimistic Chinese youngster. Although born and bro ...

  4. P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G 题解

    原题链接 POJ的链接 简要题意: 给定一张图,求多少个点,每个点都能到达它. 本题作为强连通分量的入门题. 何为强连通分量?有什么用? 下面一一解释. 首先,我们要确认,这道题目如果不用强连通分量而 ...

  5. USACO07NOV Cow Relays G 题解

    题目 For their physical fitness program, \(N (2 ≤ N ≤ 1,000,000)\) cows have decided to run a relay ra ...

  6. Codeforces Round #677 (Div. 3) E、G题解

    E. Two Round Dances #圆排列 题目链接 题意 \(n\)(保证偶数)个人,要表演一个节目,这个节目包含两种圆形舞蹈,而每种圆形舞蹈恰好需要\(n/2\)个人,每个人只能跳一种圆形舞 ...

  7. 2018年第九届蓝桥杯【C++省赛B组】B、C、D、F、G 题解

    B. 明码 #STL 题意 把每个字节转为2进制表示,1表示墨迹,0表示底色.每行2个字节,一共16行,布局是: 第1字节,第2字节 第3字节,第4字节 .... 第31字节, 第32字节 给定一段由 ...

  8. [NOI2009] 诗人小G [题解]

    诗人小G 题目大意 给出 \(n\) 个长度不超过 \(30\) 的句子,要求你对其进行排版. 对于每一行,有一个规定的行标准长度 \(L\) ,每一行的不协调度等于该行的实际长度与行标准长度差的绝对 ...

  9. FJUT寒假作业第二周G题解快速幂

    题目来源:http://210.34.193.66:8080/vj/Contest.jsp?cid=161#P6     题意:求n个数字的乘积对c取摸.主要就是有快速幂扩展到广义幂的过程. 首先题目 ...

随机推荐

  1. 用js实现简单的抛物线运动

    前言 老早就看过一些购物车的抛物线效果,也想自己凑热闹动手来实现一遍. 然后(lll¬ω¬) 书到用时方恨少,发现高中学到物理啊.数学啊,都忘光了,抛物线公式都忘了0 0. 顺手百度一波,从百度可知: ...

  2. 记 Centos zabbix-agent启动失败解决思路

    一. 环境介绍 系统版本:Centos7.4 zabbix-agent 版本:zabbix-agent 3.4.7 二. 问题现象 启动zabbix-agent时启动失败 查看zabbix-agent ...

  3. ReentrantLock原理分析

    一 UML类图 通过类图ReentrantLock是同步锁,同一时间只能有一个线程获取到锁,其他获取该锁的线程会被阻塞而被放入AQS阻塞队列中.ReentrantLock类继承Lock接口:内部抽象类 ...

  4. 1.4 Spring 依赖注入(DI)和控制反转(IOC)详解

    自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取: https://www.cnblogs.com/bclshuai/p/11380657.html 1.1  Spring 依赖注 ...

  5. vj提交时常见问题

  6. [xDebug]Xdebug和Sublime调试PHP代码

    安装xdebug 省略... 配置sublime 要调试某一个项目,首先得把这个项目在sublime下保存成一个project sublime->project->save project ...

  7. 【Java】利用反射执行Spring容器Bean指定的方法,支持多种参数自动调用

    目录 使用情景 目的 实现方式 前提: 思路 核心类 测试方法 源码分享 使用情景 将定时任务录入数据库(这样做的好处是定时任务可视化,也可以动态修改各个任务的执行时间),通过反射执行对应的方法: 配 ...

  8. TensorFlow笔记——关于MNIST数据的一个简单的例子

    这个程序参考自极客学院. from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf # MN ...

  9. vim中的替换操作

    在vim中 :s(substitute)命令用于查找并替换字符串.使用方法如下: :s/<find-this>/<replace-with-this>/<flags> ...

  10. ca76a_c++_流文件打开输入输出文件模式p773

    /*ca76a_c++_流文件打开输入输出文件模式利用文件流打开文件进行输入与输出时的选项in.out.app(附加模式).ate((end)文件打开后,定于文件结尾).trunc(裁剪).binar ...