题目要求可以转化成一个01串,让通过最少次数把序列变成中间是0,两端是1;

首先我们可以考虑一些性质:

最优解一定是每次操作都把0和1交换

这个很好理解,如果你交换同一种东西,跟没换一样

这个题卡就卡在他是一个环,由于可以两头交换,所以不好处理,我们的做法是破环为链:

对于整个环,在最优解情况下,一定有两个相邻的位置没有被交换过

如果所有相邻位置都换过,那么他就换回去了,也是无效操作,所有我们可以枚举这个点作为断点,把环视为n个序列

断点确定后,我们设置一个目标状态,就是是一种颜色(0或1)全部靠边(考场上我想的是让一种颜色靠到中间,但这样不好维护,也不好优化)

假如我们让0靠到两边,那么问题就变成:每个1靠到两边的操作次数之和

那么再给一个结论:

每个1靠到左边的花费是他左边0的个数,靠到右边是他右边0的个数

我们如果只考虑一个点的话,他要走到最左边,左边已经有一些1了,他要走的就是左边0的个数

那么现在我们就有了一个n2的暴力:

先预处理出2n长度的链的0前缀,后缀和,然后对于每段n长度的链,对其中每个1比较他走到左边和右边的花费,取min累加贡献,再对每个链的答案取最小值就行,这样有40分,前提是少用几个memset或者把数组开小!!

我们考虑优化,我们发现最优决策好像是有分界点的,对于一条n的链,一定是存在某个点,在左边的点都靠到左边,右边的点都靠到右边,这个其实很好想,哪里0少去哪里嘛,所以我们只要找到这个分界点,然后求出前面所有1靠到左边的贡献,后面所有1靠到右面的贡献就行

怎么办?预处理前缀和的前缀和

我们把1之前到i的所有0数量记为sumb[i],把

从1到i之间所有1的花费记为sum[i],我们可以看出来sum就是前缀和的前缀和

for(int i=1;i<=2*n;i++)
{
sumb[i]=sumb[i-1];sum[i]=sum[i-1];sumr[i]=sumr[i-1];
if(a[i]=='B')sumb[i]++;
if(a[i]=='R')sum[i]+=sumb[i-1],sumr[i]++;
}

蒟蒻不会用三目运算符,请见谅

sumr是1到i所有1的个数,一会要用。注意花费是之前的0个数,所以要减1

后缀和什么的也一样,下面就是如何求出差分之后的值了。

因为我们枚举到2n,现在想求从i到j的前缀和,我们看上面这个递推柿子,可以想到

把i到j的1靠到i的花费=把1到j靠到1的花费-把1到i靠到j的花费-i之前的0个数*i到j中间的1个数

就是 $$ans=sum_j-sum_{i-1}-sumb_{i-1}\times(sumr_j-sumr_{i-1}) $$

我们把i当成第一位,前面所有的0都被多算了,中间有几个1就多算了几次,减去

那么我们只有最后一个问题:分界点到底在哪???

我们当然可以二分,nlogn卡常就可过,但是他可以On:

记得上面的一句话:哪里0少往哪里移,所以最优的分界点一定是0的中点,每次取0的中点就行

另一种做法是单调指针,我们发现当区间移动的时候,分界点的移动是单调的;为什么呢?引用Yubai的证明

如果你把左边一个0移到右边,左边优的会变多,右边优的变少,指针不降(右移)

把左边一个1移到右边,只有两头发生了变化,指针不降(不动)

所以满足单调,单调指针扫过去,均摊On

下面本该贴代码结束了,但是此时

玄学做法出现了!

直接将每段序列中点视为分界点,On解决,AC

看上去没有正确性,但是经过一夜对拍之后依然没有Hack掉

实际上,它是正确的

我们考虑最终结果一定是一段连续的01串,那么他可以把1均匀分到两边,这样答案就可以取序列中点。

事实上,通过枚举区间,一定可以使得中点在0的中点区间中出现,而非中点的其他点不一定在中点区间内出现,且离中点越远出现概率越小,即

序列中点一定可以得出正确答案

所以枚举中点正确,而且码量小

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2000050;
char a[N];
int sumb[N],sufb[N],sum[N],suf[N],sumr[N],sufr[N];
inline void clear(int m)
{
for(int i=1;i<=2*m;i++)
sumb[i]=sufb[i]=sum[i]=suf[i]=sumr[i]=sufr[i]=0;
}
signed main()
{
int T;cin>>T;
while(T--)
{
scanf("%s",a+1);
int n=strlen(a+1);
for(int i=1;i<=n;i++)a[i+n]=a[i];
int ans=999999999999;
for(int i=1;i<=2*n;i++)
{
sumb[i]=sumb[i-1];sum[i]=sum[i-1];sumr[i]=sumr[i-1];
if(a[i]=='B')sumb[i]++;
if(a[i]=='R')sum[i]+=sumb[i-1],sumr[i]++;
}
for(int i=2*n;i>=1;i--)
{
sufb[i]=sufb[i+1];suf[i]=suf[i+1];sufr[i]=sufr[i+1];
if(a[i]=='B')sufb[i]++;
if(a[i]=='R')suf[i]+=sufb[i+1],sufr[i]++;
}
for(int i=1;i<=n;i++)
{
int p=i+n-1,j=(i+p)/2;
int qz=sum[j]-sum[i-1]-sumb[i-1]*(sumr[j]-sumr[i-1]),
hz=suf[j]-suf[p+1]-sufb[p+1]*(sufr[j]-sufr[p+1]);
ans=min(ans,qz+hz);
}
printf("%lld\n",ans);
clear(n);
}
}

我的常数大,因为我太菜了

这种东西觉得想明白了收获还是挺大的,真正追求的不只是那个绿勾,还有题背后的东西

执.

模拟7 T3 寿司题解的更多相关文章

  1. 【2018.06.26NOIP模拟】T3节目parade 【支配树】*

    [2018.06.26NOIP模拟]T3节目parade 题目描述 学校一年一度的学生艺术节开始啦!在这次的艺术节上总共有 N 个节目,并且总共也有 N 个舞台供大家表演.其中第 i 个节目的表演时间 ...

  2. [NOIP10.4模拟赛]3.z题解--思维

    题目链接: 咕咕 闲扯: 哈哈这道T3考场上又敲了5个namespace,300+行,有了前车之鉴还对拍过,本以为子任务分稳了 结果只有30分哈哈,明明用极限数据对拍过不知怎么回事最后数据又是读不全, ...

  3. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  4. 【2018暑假集训模拟一】Day1题解

    T1准确率 [题目描述] 你是一个骁勇善战.日刷百题的OIer. 今天你已经在你OJ 上提交了y 次,其中x次是正确的,这时,你的准确率是x/y.然而,你最喜欢一个在[0; 1] 中的有理数p/q(是 ...

  5. 20180711模拟赛T3——聚变

    文件名: fusion 题目类型: 传统题 时间限制: 3秒 内存限制: 256MB 编译优化: 无 题目描述 知名科学家小A在2118年在计算机上实现了模拟聚变的过程. 我们将她研究的过程简化. 核 ...

  6. 20180520模拟赛T3——chess

    [问题描述] 小美很喜欢下象棋. 而且她特别喜欢象棋中的马. 她觉得马的跳跃方式很独特.(以日字格的方式跳跃) 小芳给了小美一张很大的棋盘,这个棋盘是一个无穷的笛卡尔坐标. 一开始\(time=0\) ...

  7. [NOIP10.6模拟赛]2.equation题解--DFS序+线段树

    题目链接: 咕 闲扯: 终于在集训中敲出正解(虽然与正解不完全相同),开心QAQ 首先比较巧,这题是\(Ebola\)出的一场模拟赛的一道题的树上强化版,当时还口胡出了那题的题解 然而考场上只得了86 ...

  8. 2019.6.20 校内测试 NOIP模拟 Day 1 分析+题解

    这次是zay神仙给我们出的NOIP模拟题,不得不说好难啊QwQ,又倒数了~ T1 大美江湖 这个题是一个简单的模拟题.   ----zay 唯一的坑点就是打怪的时候计算向上取整时,如果用ceil函数一 ...

  9. [CSP-S模拟测试50]反思+题解

    ??大部分人都觉得T3是道不可做题去刚T1T2了,于是我就侥幸苟到了前面? 这场考试比较成功的就是快速水掉了T1T2的部分分,1h拿到88分起码为之后硬肝T3上了保险(赛后发现就算T3爆零也能rank ...

随机推荐

  1. XCTF Normal_RSA

    这题本来算是很常规的rsa了,下载附件 发现有个公钥文件,还有一个加密文件,这种题之前有遇到一次,做法和这个类似,上次那个是用rsa的库,直接解的,这次直接用常规的,好像更简单,记录下模板 记事本打开 ...

  2. 文末送书四本 | 这篇Java反射机制太经典!不看后悔!

    先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索[程序职场]关注这个执着的职场程序员. 价值:Java技能,面试经验指导,简历优化,职场规划指导,技能提升方法,讲不完的职场故事,个人成长经 ...

  3. MVP on Board 没用小技巧 👌

    七月入选了微软 MVP,本文记录 on board 过程中遇到的小问题和没用小技巧. MVP Portal 当你收到来自微软的确认邮件之后,你将正式被接纳为微软现任 MVP 的一员.从此刻开始,你便拥 ...

  4. Java程序设计(2021春)——第三章类的重用笔记与思考

    Java程序设计(2021春)--第三章类的重用笔记与思考 本章概览: 3.1 类的继承(概念与语法) 3.2 Object类(在Java继承最顶层的类) 3.3 终结类和终结方法(只能拿来用,不可以 ...

  5. Python3 MySQL 数据库连接 - PyMySQL 驱动

    什么是 PyMySQL? PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb. PyMySQL 遵循 Python 数据库 AP ...

  6. 【论文阅读】DSDNet Deep Structured self-Driving Network

    前言引用 [2] DSDNet Deep Structured self-Driving Network Wenyuan Zeng, Shenlong Wang, Renjie Liao, Yun C ...

  7. 【LeetCode】86. 分隔链表

    86. 分隔链表 知识点:链表: 题目描述 给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前. 你应当 保留 两个 ...

  8. .net core番外第2篇:Autofac的3种依赖注入方式(构造函数注入、属性注入和方法注入),以及在过滤器里面实现依赖注入

    本篇文章接前一篇,建议可以先看前篇文章,再看本文,会有更好的效果. 前一篇跳转链接:https://www.cnblogs.com/weskynet/p/15046999.html 正文: Autof ...

  9. YsoSerial 工具常用Payload分析之CC3(二)

    这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...

  10. [NOI 2021] 轻重边 题解

    提供一种和不太一样的树剖解法(一下考场就会做了qwq),尽量详细讲解. 思路 设重边为黑色,轻边为白色. 首先,先将边的染色转化为点的染色(即将 \(u\) 节点连向父节点的边的颜色转化为 \(u\) ...