当前位置: 首页 > article >正文

[Atcoder Beginner Contest 381 D]1122 Substring 题解

这道题在赛场上没调过,本蒟蒻想纪念一下。

题目翻译

一个数字串 S S S 是 1122 串,需要满足:

  1. ∣ S ∣ |S| S,即 S S S 的长度是偶数。
  2. 对于每一个满足 1 ≤ i ≤ ∣ S ∣ 2 1\le i \le \frac{|S|}{2} 1i2S整数 i i i S 2 i − 1 = S 2 i S_{2i-1}=S_{2i} S2i1=S2i
  3. 每个在 S S S 中出现过的数字都恰好出现两次。

用人话来说,就是有一个串长成这样:AABBCC,然后不能出现重复的对子,比如 AABBCCAA 就不合法。现在给你一个长度为 N N N 的数组 A i A_i Ai,请问其中最长的 1122 串的长度是多少?

思路

由于 1122 串是成双成对出现的,分成两种情况讨论。

  1. 从一个奇数下标开始的 1122 串。
  2. 从一个偶数下标开始的 1122 串。

我们可以枚举右端点 i i i,用 l l l 维护左端点。 i i i 每次加 2 2 2,如果遇到 A i A_{i} Ai A i + 1 A_{i+1} Ai+1 不等的情况,就将 l l l 赋值为 i + 2 i+2 i+2,表示 A i A_{i} Ai A i + 1 A_{i+1} Ai+1 不能被包含在一个 1122 串里。如果遇到一个 A i A_{i} Ai 与之前的某个 A j A_{j} Aj 相等,那么就得把之前的 A j A_{j} Aj 排除到 1122 串外面,所以还得用 p s i ps_{i} psi 记录值为 i i i 的上一个下标,如果发现 i ≥ l i\ge l il,那么 l = i + 2 l=i+2 l=i+2。注意这里不会出现将一对的 A i A_{i} Ai 判断为重复的情况,因为 i i i 每次加 2 2 2,跳过了 i + 1 i+1 i+1 a n s ans ans 就取 i + 1 − l + 1 i+1-l+1 i+1l+1 的最大值。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxlog 63
int n,a[400005],ps[400005],ans;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i],ps[a[i]]=-10;
	int l=1;
	for(int i=1;i<=n;i+=2){
	//不需要特判i+1大于n的情况,因为a[i]>=1而a[n+1]=0,会被a[i]!=a[i+1]这一条卡掉
		if(a[i]!=a[i+1]) l=i+2;
		if(ps[a[i]]+2>l) l=ps[a[i]]+2;
		ps[a[i]]=i;
		ans=max(ans,i+1-l+1);//1.注意末端是i+1不是i
	}
	for(int i=1;i<=n;i++) ps[a[i]]=-10;
	l=2;//2.注意从2开始
	for(int i=2;i<=n;i+=2){
		if(i+1>n) continue;
		if(a[i]!=a[i+1]) l=i+2;
		if(ps[a[i]]+2>l) l=ps[a[i]]+2;
		ps[a[i]]=i;
		ans=max(ans,i+1-l+1);
	}
	cout<<ans<<endl;
	return 0;
}

其实还有一种思路,但是本人的代码目前还过不了,如果有哪位大佬看出问题了,欢迎留言

把连续的相同的数字缩成一个,并记录是几个数字缩成的,用 f l fl fl 表示,当 f l = 0 fl=0 fl=0 时就是单个数字, f l = 1 fl=1 fl=1 时就是两个数字, f l > 1 fl>1 fl>1 就是多个数字。比如:

18
1 1 1 2 2 3 3 3 4 4 1 1 3 3 3 3 1 2

就会变成:(右边一列是 f l fl fl,左边是 v v v

1 2
2 1
3 2
4 1
1 1
3 3
1 0
2 0

观察一下可以发现,如果 f l = 0 fl=0 fl=0,就不能包含在 1122 串里面,如果 f l = 1 fl=1 fl=1 就可以包含在 1122 串里面,如果 f l > 1 fl>1 fl>1 就只能在 1122 串的头或者尾,取这些相同的数字中的前两个或者后两个,但不能让 1122 串跨过这些数字,否则一个数字出现的次数就不符合标准了。仍旧以相同的方式维护 l l l

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxlog 63
int n,a[400005],tot,ps[400005],ans;
struct node{
	int v,f;
} b[400005];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++){
		if(i>1&&a[i]==a[i-1]) b[tot].f++;
		else b[++tot].v=a[i],b[tot].f=0;
	}
	int l=1;
	for(int i=1;i<=tot;i++){
		if(b[i].f==0) l=i+1;
		if(b[i].f>1){
			ans=max(ans,i-l+1);
			l=i;
		}
		if(ps[b[i].v]>=l) l=ps[b[i].v]+1;
		ps[b[i].v]=i;
		ans=max(ans,i-l+1);
	}
	cout<<ans*2<<endl;
	return 0;
}

http://www.kler.cn/a/408301.html

相关文章:

  • android-sdk 安装脚本
  • java @Override 详解
  • 【SQL Server】华中农业大学空间数据库实验报告 实验三 数据操作
  • 瑞佑液晶控制芯片RA6807系列介绍 (三)软件代码详解 Part.10(让PNG图片动起来)完结篇
  • 初学 flutter 环境变量配置
  • mysql根据日期查询没有的日期也要显示数据
  • GWO-SVMD分解 | Matlab实现GWO-SVMD灰狼算法优化逐次变分模态分解
  • Linux应用编程(C语言编译过程)
  • vue2面试题10|[2024-11-24]
  • .NET新知识点笔记
  • 【STM32】GPIO(超详细)
  • 内存分配与回收策略
  • 设计模式——模板模式
  • (二)Sping Boot学习——Sping Boot注意事项
  • 【踩坑日记】【教程】如何在ubuntu服务器上配置公钥登录以及bug解决
  • 分布式数据库中间件可以用在哪些场景呢
  • 【Y20030006】基于php+mysql的课程学习网站的设计与实现(附源码 配置 文档)
  • w055基于web的服装生产管理的设计与实现
  • 【设计模式】如何用C++实现适配器模式
  • Odoo :免费且开源的农牧行业ERP管理系统
  • 什么是 C++ 中的类型别名和 using 声明?如何使用类型别名和 using 声明?
  • Ultiverse 和web3新玩法?AI和GameFi的结合是怎样
  • RT-DETR融合[ECCV 2018]RCAN中的RCAB模块及相关改进思路
  • 《C++智能合约与区块链底层交互全解析:构建坚实的去中心化应用桥梁》
  • 微知-lspci访问到指定的PCIe设备的几种方式?(lspci -s bus;lspci -d devices)
  • Leetcode 每日一题 15.三数之和