题目链接 https://www.luogu.com.cn/problem/P2882

分析

这个题来看的话好像有点难下手,不如再去读一遍题 N遍,发现一句话很重要Each time the machine is used, it reverses the facing direction of a contiguous group of K cows in the line,就是说只能翻转固定的长度区间,那这样是不是就可以枚举区间了?枚举一层区间,再枚举每次起点,最后加上区间修改,时间复杂度\(O(N^3)\),肯定会T掉,接下来就考虑优化了。

优化怎么入手呢?时间主要就是出在这三层循环上,只要省掉一层循环,时间复杂度就能到\(O(N^2)\),这样就可以过,第一层循环,显然不能省略,第二层同样,只有在区间修改这一层循环上可以做点手脚,回忆区间修改,有几种做法,线段树,树状数组,还有差分,前两者用在这都有点大材小用或是说不是很合适,因为判断是否区间修改完成不好判断,而差分用在这个区间上就很合适了。那我们大概思路也就有了,首先读入数组,将B标记成1,F标记成0,这里怎么标记都无所谓,然后利用枚举区间,差分修改,最后输出答案,下面考虑一下细节。

我们枚举区间完,要从左到右一次反转区间,为什么呢?题目中要求的是最小次数,就是要先保证次数最小,再考虑区间长度,而我们如果先修改后面的,把后面改好了,再去改前边的,结果一定不会比先改前边的好(有可能相等,如00100),所以我们为保证最小次数,一定从最左端开始依次枚举,如果这个点不符合,就把他后面的整个区间翻转,这里就要用到差分了,肯定直接修改会T掉,我们可以考虑,如果这个区间要修改,那么原来的1会变成2,0会变成1,好像没什么规律,但再看就发现所有的奇数都需要改变,偶数就不用,每次修改给整个区间加一,判断奇偶数就行,然后这就变成了一个区间加一个数的操作,相信大家应该都会。这样修改就完成了,那么怎么判断能不能完成题目的任务呢?由题意可以知道如果当前区间长度小于修改的区间长度,是不能修改的,也就是从n往前的长度为len的区间总是无法被修改的,所以判断这一段区间内有无不满足条件的点即可。

最后找答案的时候也有一个地方,就是当操作修改次数不同时,直接用操作修改次数最小的那个答案就行,但如果当前操作次数和原来答案相同,是不是要考虑一下区间长度改成最小值?答案显然是不是,…………,因为我们是从小到大枚举的区间长度,所以在遇到相等的时候,已经得到的答案的区间长一定是小的,所以只在次数不同时修改答案,但判断上也不会错。

其他优化

当然以下优化不加也没问题,毕竟算法时间复杂度足够过掉这道题。

我做完之后看了看时间大概700ms左右,好像有点高,看别人的时间好像没有特别大,所以我加了加小优化。



为方便说,由上到下一次标号\(1-4\),1,2跑的时间还是挺快的但没啥用,\(NOIp\)不可能给你开O2也不可能给你c++17,所以还是看一下3和4,这俩时间大概有一倍的关系,看一下代码吧

3

#include<cstdio>
#include<cstring>
using namespace std;
const int N=5e3+10;
char s[3];
int cf[N],a[N];
int min(int a,int b){
if(a<b)return a;
else return b;
}
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s);
if(s[0]=='B')a[i]=1;
else a[i]=0;
}
int res=0x3f3f3f3f,ans=0x3f3f3f3f;
for(int len=1;len<=n;len++){
int cnt=1,k=0;memset(cf,0,sizeof(cf));
for(int i=1;i<=n;i++){
cf[i]+=cf[i-1];
if(i+len-1<=n){
if(a[i]+cf[i]&1){
cf[i]++;cf[i+len]--;k++;
}
}else if(cf[i]+a[i]&1){cnt=0;break;}
}
if(cnt)
if(k<ans){
ans=k;res=len;
}
else if(k==ans)res=min(res,len);
}
printf("%d %d",res,ans);
return 0;
}

4

#include<cstdio>
#include<cstring>
using namespace std;
const int N=5e3+10;
char s[3];
int cf[N],a[N];
int min(int a,int b){
if(a<b)return a;
else return b;
}
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s);
if(s[0]=='B')a[i]=1;
else a[i]=0;
}
int res=0x3f3f3f3f,ans=0x3f3f3f3f;
for(int len=1;len<=n;len++){
int cnt=1,k=0;memset(cf,0,sizeof(cf));
for(int i=1;i<=n;i++){
cf[i]+=cf[i-1];
if(i+len-1<=n){
if(a[i]+cf[i]&1){
cf[i]++;cf[i+len]--;k++;
}
}else if(cf[i]+a[i]&1)cnt=0;
}
if(cnt)
if(k<ans){
ans=k;res=len;
}
else if(k==ans)res=min(res,len);
}
printf("%d %d",res,ans);
return 0;
}

其实就是少一个break,感觉这个加上还是很有必要的,因为可能极限数据的时候,CCF那评测机状态不好,再卡一下,可能会出问题。

问题

那么有没有可能最开始全部是朝前的呢?答案是没有,英文题面中已经讲到,有一些牛,所以说不可能其实全部朝前边的。

USACO07MAR Face The Right Way G 差分的更多相关文章

  1. [USACO07MAR]Face The Right Way G

    发现选定一个长度后,怎么翻转是固定的. 那我们直接选定一个长度去操作就行. 优化操作过程 类似于堆里打持久化标记一样的感觉. [USACO07MAR]Face The Right Way G // P ...

  2. 洛谷 P2882 [USACO07MAR]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 ...

  3. luogu P2882 [USACO07MAR]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 forwar ...

  4. BZOJ3453: tyvj 1858 XLkxc(拉格朗日插值)

    题意 题目链接 Sol 把式子拆开,就是求这个东西 \[\sum_{i = 0} ^n \sum_{j = 1}^{a + id} \sum_{x =1}^j x^k \pmod P\] 那么设\(f ...

  5. BZOJ4650:[NOI2016]优秀的拆分——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4650 https://www.luogu.org/problemnew/show/P1117 如果 ...

  6. 『题解』[NOI2016]优秀的拆分

    如果一个字符串可以被拆分为\(AABB\)的形式,其中$A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串\(aabaabaa\),如果令\(A=aab\),\(B=a\ ...

  7. CodeChef DGCD Dynamic GCD

    CodeChef题面 Time limit 210 ms Code length Limit //内存限制也不说一下,真是的-- 50000 B OS Linux Language limit C, ...

  8. Storyboards Tutorial 03

    这一节主要介绍segues,static table view cells 和 Add Player screen 以及 a game picker screen. Introducing Segue ...

  9. 文件图标SVG

    ​<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink ...

随机推荐

  1. 7-29 jmu-python-不同进制数 (10 分)

    输入一个十进制整数,输出其对应的八进制数和十六进制数.要求采用print函数的格式控制进行输出,八进制数要加前缀0o,十六进制数要加前缀0x. 输入格式: 输入一个十进制整数,例如:10 输出格式: ...

  2. go 下载qq音乐

    //go下载qq音乐 package main import ( _ "fmt" jsoniter "github.com/json-iterator/go" ...

  3. Vuex的理解以及它的辅助函数

    理解:vue中的“单向数据流”,这里借用官网的图示: Vue是单向数据流,v-model只是语法糖而已.单向数据流就是:数据总是[向下传递]从父级组件传递给子组件,只能单向绑定.子组件内部不能直接修改 ...

  4. 第一篇博客 C+++知识点总结一

    1.成员 1.比较特殊的成员类型:protected. 保护成员在本类中和private类型的成员作用一模一样.区别在于保护成员可以由本类的派生类的成员函数访问,但是私有成员在其派生类中无法访问. 2 ...

  5. 求你了,别再说Java对象都是在堆内存上分配空间的了!

    Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点,所以,即使是一个Java的初学者,也一定或多或少的对JVM有一些了解.可以说,关于JVM的相关知识,基本是每个Java开发者 ...

  6. CentOS安装docker ce的三种方式

    参考文章: CentOS安装docker ce的三种方式: 1.环境 CentOS Linux release 7.6.1810 (Core) 2.卸载旧版本 sudo yum remove dock ...

  7. HTTP中主要的头字段

    HTTP中主要的头字段 头字段类型 含义 备注 通用头:适用于请求和响应消息的头字段 Date 表示请求和响应生成的日期   Pragma 表示数据是否允许缓存的通信选项   Cache-Contro ...

  8. js Array方法总结

    修改器方法(9) copyWithin(target: number, start: number, end?: number): this; // 浅复制数组的一部分到同一数组中的另一个位置,并返回 ...

  9. 使用Netty如何解决拆包粘包的问题

    首先,我们通过一个DEMO来模拟TCP的拆包粘包的情况:客户端连续向服务端发送100个相同消息.服务端的代码如下: AtomicLong count = new AtomicLong(0); NioE ...

  10. Jsp el表达式无解析 解决

    需要开启 el isELIgnored="false" 这时已经可以正常访问了