首页 > 其他分享 >洛谷-P9574 题解

洛谷-P9574 题解

时间:2024-08-05 19:39:15浏览次数:13  
标签:BTTB ... le 洛谷 推论 P9574 题解 传递性 区块

思路分析

分析样例:

== TTBT BTTBTB TTT BTTB
-> TTBT TBBTTB TTT BTTB
-> TTBT TBTBBT TTT BTTB
-> TTBT TBTBBT TTT TBBT
----1-----2-----3---4--

观察区块 2,发现 BTTB 进行操作后与右边的 TB 再次构成 BTTB,我们发现在这个区块内,可以从左向右不断操作,我们称这种特性为传递性,可以发现其具有方向。

假设区块 2 右边有更多的 TB,例如 BTTBTBTBTBTB,是否仍然存在传递性呢?没错,你可以在纸上试一下,答案肯定。

推论 1:具有 BTTB TBTB... 特征的区块中,可以向右不断操作,操作具有传递性,方向向右。

那我们再反过来看呢?难道就不能向左不断操作吗?

我们在区块 2 的左边加上一些 BT,可以发现可以不断向左传递。

推论 1.1:BTTB TBTB... 具有向右的传递性;...BTBT BTTB 具有向左的传递性。

综合一下:

推论 1.2:...BTBT BTTB TBTB... 具有双向的传递性,在它的右方传递性向右,左方则向左。

考虑极限思维,...BTBT BTTB TBTB... 舍去了它的尾巴,变成 BTTB。思考发现这也是具有双向传递性的,只不过只能连续操作 1 次。

推论 1.3:BTTB 也具有双向传递性。

那么,这有什么用呢?

再次观察样例(如上),可以发现通过传递性进行操作,区块 3 左边多加了一个 T,右边也多加了一个 T。是的,我们可以通过区块的传递性对某个连续 T 区间增加 T

我们对推论 1.1 再次分析,对于区间 BTTB TBTB...,可以发现右边的 B 变成了 T;而对于区间 ...BTBT BTTB,左边的 B 变成了 T

由于区块 3 在区块 2 右边,区块 2 表现出向右的传递性,通过操作区块 2 右边的 B 变成 T,由于两个区块相邻,区块 3 连续 T 的长度增加 1。同理区块 4 表现出向左的传递性,邻接于区块 3,使得区块 3 连续 T 在右边又增加了 1。

推论 2:对于一个具有传递性的区块,它可以使它表现出的传递性方向上的邻接连续 T 区块长度增加 1。

可以发现,当某个具有传递性的区块进行操作后,它将损失其传递性,不再可操作,不再能给邻接 T 区块提供新的 T。也就是说:

推论 3:一个具有传递性的区块只能对其表现出的传递性方向上的邻接连续 T 区块贡献一次。

综合推论 2 和推论 3,我们可以得出推论 4:一个连续 T 区块只能收到两次贡献,来自左和右的两个方向,也就是说,每个连续 T 区间长度最多增加 2,其增加的 T 分别来源于左边和右边两个方向的与其方向相反的连续性区块。

从推论 4 的视角,我们再来看一次样例,我们把表现出向右连续性的区块视为 ->,向左的视为 <-

TTBT -> TTT <-

可以看出连续性的方向对答案是存在影响的。

如此,我们找到每个具有连续性的区块,区块左边表现出向左的连续性,并打上标记,向右也是如此,但注意要区分方向。

然后枚举一遍连续 T 区块,如果其某个边界处存在标记且该标记方向正确,则该方向使长度加 1,最后取所有区块这样执行后的长度的最大值即可。

蒟蒻已经尽力说清楚了 QAQ。

代码实现

#define by_wanguan
#include<iostream>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=5e5+7;
int t,n,le[N],ri[N],ans; char c[N];
int main(){
  ios::sync_with_stdio(false),cin.tie(0);
  cin>>t; while(t--){
  cin>>n; for(int i=2;i<=n+1;i++) cin>>c[i],le[i]=ri[i]=0;
  int l=1,r=l+3; ans=0; c[0]=c[1]=c[n+2]=c[n+3]='#';
  le[0]=le[1]=le[n+2]=le[n+3]=ri[0]=ri[1]=ri[n+2]=ri[n+3]=0;//初始化
  while(r<=n){//通过双指针查找有连续性的区间
    l++,r++;
    if(c[l]=='B'&&c[l+1]=='T'&&c[l+2]=='T'&&c[l+3]=='B'){
	  ri[r]++,le[l]++;//发现存在,则在两端打上标记,le的标记方向向左,ri向右
      while(c[r+1]=='T'&&c[r+2]=='B') r+=2,ri[r]++;//向左右扩展区块并打上标记(找尾巴)
      while(c[l-1]=='T'&&c[l-2]=='B') l-=2,le[l]++;
      l=r-1,r=l+3;//l跳到r的位置,在本次操作后l和r都会++,提前减1
    }
  }
  l=1,r=l;
  while(r<=n){
    l=r,l++,r++;
    if(c[l]!='T') continue;//查询连续T区间
    while(c[r+1]=='T') r++;//扩展连续T区间
    ans=max(r-l+1+ri[l-1]+le[r+1],ans);//查询是否存在标记,注意方向
  }
  cout<<ans<<'\n';
}
}

有点 DP 的味道,看不懂请狠狠踢我!蒟蒻会尽量解答的。

喵。

标签:BTTB,...,le,洛谷,推论,P9574,题解,传递性,区块
From: https://www.cnblogs.com/wanguan/p/18343918

相关文章

  • AT_abl_e Replace Digits 题解
    题目传送门前置知识线段树解法需要维护区间信息,考虑使用线段树维护。预处理出\(\overline{xx\dotsx}\),其中\(x\in\{1,2,3,4,5,6,7,8,9\}\),便于区间赋值。然后就是普通的线段树板子了。代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#de......
  • AGC027C 题解
    注意到如果可以构造出所有由\(\texttt{A}\)和\(\texttt{B}\)组成的字符串,那么在图上游走的路径必须成环,并且的环上的每一个点都必须同时有一个\(\texttt{A}\)邻居和\(\texttt{B}\)邻居。于是可以考虑把点拆分为入点和出点,相邻两个点为\(\texttt{AA},\texttt{BB}\)的,从......
  • npm下载包时报错 Unexpected token ‘.‘问题解决
    项目场景:项目需要使用node18.12.0以上版本的,但是npm下载显示异常问题描述当通过nvm切换nodejs版本为16以上时,npminstall[package]报错:Unexpectedtoken'.'原因分析:提示:该问题不是npm的问题,也不是nodejs的问题,是nvm-windows的问题我是通过nvm-windows已经更新版本......
  • 洛谷P1223 排队接水
    P1223排队接水题目描述有\(n\)个人在一个水龙头前排队接水,假如每个人接水的时间为\(T_i\),请编程找出这\(n\)个人排队的一种顺序,使得\(n\)个人的平均等待时间最小。输入格式第一行为一个整数\(n\)。第二行\(n\)个整数,第\(i\)个整数\(T_i\)表示第\(i\)个人的......
  • 《数据结构习题解析与实验指导_李冬梅,张琪编著》总结出的大纲
        下面大纲为《数据结构习题解析与实验指导_李冬梅,张琪编著》总结出的大纲,可装13学习下:          ......
  • Codeforces Round 963 (Div. 2) D题解
    CodeforcesRound963D题目描述给定两个正整数n和k以及另一个由n个整数组成的数组a。在一次操作中,可以选择a中大小为k的任意一个子数组,然后将其从数组中删除,而不改变其他元素的顺序。更正式地说,假设(l,r)是对子数组a[l],a[l+1],...,a[r]的操作,使得r-l+1......
  • leetcode200. 岛屿数量C++题解,精美图例和流程图,一题带你弄懂图的dfs遍历算法
    leetcode200.岛屿数量给你一个由‘1’(陆地)和‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。示例1:输入:grid=[[“1”,“1”,“1”,......
  • [POI2015] POD 题解
    前言题目链接:洛谷。题意简述长度为\(n\)的一串项链,每颗珠子是\(k\)种颜色之一。第\(i\)颗与第\(i-1,i+1\)颗珠子相邻,第\(n\)颗与第\(1\)颗也相邻。切两刀,把项链断成两条链。要求每种颜色的珠子只能出现在其中一条链中。求方案数量(保证至少存在一种),以及切成的两段......
  • CF1993C Light Switches 题解
    CF1993CLightSwitches题解题目大意有\(n\)盏灯,第\(i\)盏灯亮着的时间为\([a_i+bk,a_i+(b+1)k-1]\),其中\(k\)为给定常数,\(b\)为任意非负偶数。求一个最小的\(t\),使得在时间\(t\)所有灯都是亮着的。Solve令\(m=2k\),显然所有灯的开关状态以\(m\)为周期,所以我们......
  • 洛谷P1001 A+B Problem的一些歪解(淼作)
    一、LCT#include<iostream>#include<cstring>#include<cstdio>#include<cstring>usingnamespacestd;structnode{intdata,rev,sum;node*son[2],*pre;booljudge();boolisroot();voidpushdown();voidupda......