感觉 \(O(tn^2)\) 不是正解,于是弱弱的发了一波 \(O(tn)\) 。

题意描述

你谷还没有人翻译,这里就简单介绍一下。

给你一个长为 \(n\) 的序列,如果它的一个长度至少为 \(3\) 的子集可以构成回文,

回答 \(YES\) ,否则回答 \(NO\) 。(题目有多组数据)

题目 传送门

算法分析

简化题意

首先本题要求找到一个长度至少为3的回文子串,显然可以将题目转化为:

找到一个长度为 3 的回文子串。

  1. 如果原回文子串的长度为奇数,显然可以删除两边的数字,使其长度减少为 \(3\) 。
  2. 如果原回文子串的长度为偶数,可以删除中间两个字符中的一个,使其变为奇数,再重复上述步骤。

举个栗子

  1. 奇数:\(1234321 ->343\)。
  2. 偶数:\(123321->12321->232\)。

所以得出结论:如果一个序列符合要求,它必然有一个长度为3的回文子串

朴素算法

得到上述结论之后,我们很容易想到一个朴素做法:

枚举其中间节点,向两边延伸,看有没有相同的数字。

但是显然,这个做法的时间是 \(O(tn^2)\) 的,大数据下是跑不过去的。

所以我们需要一点优化。

时间优化

排除冗余操作

假设我们从左往右推导,已经到了第 \(i\) 个(其中第 \(1-(i-1)\) 中没有符合条件的节点)

显然,在朴素算法中,我们需要将 \(1\)~\((i-1)\) 一一与右边 \((i+1)\)~\(n\) 比较,但是这是没有必要的。

首先显然第 \(i-2\) 个节点在进行到第 \(i-1\) 节点是就已经与右边进行了比较

同理第 \(i-2\)~\(1\) 个节点早已进行过比较了,且比较不成功,所以再比较是重复而无用的

所以得出结论:

进行到第 \(i\) 个节点时,只需要比较第 \(i-1\) 个节点与右边数值的大小即可。

可惜这并没有优化多少,所以最重要的优化就来了 (尖叫声)

改变处理顺序

记 \(vis[i]\) 表示 \((i+2)\)~\(n\) 中有没有与 \(i\) 相同的数。(注意这里不是 i+1,因为 i+1 是中间节点

这个 \(i+2\) 开始如果没有看懂的话也没有关系,记住就可以了,下文会给出详细讲解。

因为 \(vis[i]\) 的值仅与 \((i+2)\)~\(n\) 有关,所以不妨从后往前进行处理。(想一想为什么)

每次处理时,查看 \(vis[i]\) 的值,如果 \(vis[i]==1\) ,说明前面有与之相同的数值,于是果断return true

否则将 \(vis[i+2]=true\) ,继续处理下一个数。

至此,本题得到完美解决。

手玩样例说明

这里仅仅准备给那些上面没看懂的同学们,如果说你看懂了上面的全部,你可以去打代码了。

这里沿用样例二样例五以及一个自编样例来展开说明。

样例二

5

1 2 2 3 2

从后往前枚举(从 \(n-2\) 开始即可,想一想为什么)。

  1. 第 \(n-2\) 位,\(dis[a[n]]=true\)(即 \(dis[2]=true\)),发现 \(dis[a[n-2]]==true\),果断 return true
  2. 第 \(n-3\) 位,\(dis[a[n-1]]=true\)(即 \(dis[3]=true\)),发现 \(dis[a[n-3]]==true\),果断 return true
  3. 第 \(n-4\) 位,\(dis[a[n-2]]=true\) (即 \(dis[2]=true\)),发现 \(dis[a[n-4]]==false\),结束操作。

所以答案为 \(YES\)。

其实在第一次操作时便可以结束了,但是为了让读者理解,硬是做下去了**。

样例五

10

1 1 2 2 3 3 4 4 5 5

  1. 第 \(n-2\) 位,\(dis[a[n]]=true\)(即 \(dis[5]=true\)),发现 \(dis[a[n-2]]==false\),去下一位。
  2. 第 \(n-3\) 位,\(dis[a[n-1]]=true\)(即 \(dis[5]=true\)),发现 \(dis[a[n-3]]==false\),去下一位。
  3. 第 \(n-4\) 位,\(dis[a[n-2]]=true\) (即 \(dis[4]=true\)),发现 \(dis[a[n-4]]==false\),去下一位。
  4. ......
  5. 第 \(1\) 位,\(dis[a[3]]=true\) (即 \(dis[2]=true\)),发现 \(dis[a[1]]==false\),结束操作。

所以答案为 \(NO\)。

这里让我们回忆刚才的疑问:从 \(i+2\) 开始比较。从这里可以看出,如果从 \(i+1\) 开始,答案为 \(YES\)

因为如果 \(a[i]==a[i+1]\) ,只能得到两个相邻的数相邻,而不能得到一个回文子串

自编样例

9

1 3 7 5 8 0 2 5 9

  1. 第 \(n-2\) 位,\(dis[a[n]]=true\)(即 \(dis[9]=true\)),发现 \(dis[a[n-2]]==false\),去下一位。
  2. 第 \(n-3\) 位,\(dis[a[n-1]]=true\)(即 \(dis[5]=true\)),发现 \(dis[a[n-3]]==false\),去下一位。
  3. 第 \(n-4\) 位,\(dis[a[n-2]]=true\) (即 \(dis[2]=true\)),发现 \(dis[a[n-4]]==false\),去下一位。
  4. 第 \(n-5\) 位,\(dis[a[n-3]]=true\)(即 \(dis[0]=true\)),发现 \(dis[a[n-5]]==true\),操作结束。

所以答案为 \(YES\)。

请读者自行理解,这是正常操作

代码实现

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#define N 5010
using namespace std; int n,T,a[N];
bool flag,vis[N]; int main(){
scanf("%d",&T);
while(T--){
memset(vis,false,sizeof(vis));
flag=false;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=n-2;i>=1;i--){
vis[a[i+2]]=true;//一定要先赋值
if(vis[a[i]]){
printf("YES\n");
flag=true;
break;
}
}
if(!flag) printf("NO\n");
}
return 0;
}

码量很小,简单易懂吧。

结语

学 \(OI\) 一定要具备将复杂问题简单化的能力,同时也要多做题,积累优化思路。

如果这篇文章对你有帮助,你懂的。

完结撒花。

CF1324B的更多相关文章

  1. CF1324B Yet Another Palindrome Problem 题解

    原题链接 CF 127个测试点,好评 简要题意: 多组数据,问数组中是否有长度 \(\geq 3\) 的回文子序列. 我们需要找到本质. 题目不让我们求这个长度,只让我们判断,这是为什么呢? 如果答案 ...

随机推荐

  1. python3 连接数据库~

    ~目前记录的是针对python3写的数据库连接,不适用于pyhon2.python3如果想要与数据库进行连接,则需要先下载对应各数据库的插件包,然后导入包.python3的插件下载地址:https:/ ...

  2. GOOGLE工作法(世界一速)|木深读书笔记

  3. 《C++ primerplus》第13章练习题

    1.对CD类的派生练习.基类CD类存储作者和作品号等信息,派生类Classic额外增加一格"主要作品"的信息.主函数使用拷贝构造函数.按引用传递参数的函数和指针来测试基类和派生类的 ...

  4. golang常用库:配置文件解析库-viper使用

    一.viper简介 viper 配置解析库,是由大神 Steve Francia 开发,他在google领导着 golang 的产品开发,他也是 gohugo.io 的创始人之一,命令行解析库 cob ...

  5. 使用css实现轮播图

    使用css3实现图片轮播 前言:实现图片轮播的方式有很多种 ,例如js ,css 等等. 本文主要讲述使用纯css3实现轮播图 工具介绍: 使用的编辑器: Hbuilder 进入正题 html代码: ...

  6. shell-的特殊变量-难点理论

    一:shell的特殊变量-难点理论  1. $*和$@的区别例子     $* 将所有的命令行所有参数视为单个字符串,等同于"$1$2$3"     $@ 将命令行每个参数视为单独 ...

  7. 多测师讲解ui自动化框架设计思想_高级讲师肖sir

    UI自动化框架:UI自动化框架可以分为8个模块,conf.data.public.pageobject.testcase.runner.report.log.conf是用来储存系统环境.数据库.邮件的 ...

  8. 多测师_肖sir_性能测试之性能测试了解001(jmeter)

    一.了解jmeter 1.Jmeter的概念? JMeter是Apache组织开发的基于Java的压力测试工具.具有开源免费.框架灵活.多平台支持等优势.除了压力测试外,JMeter在接口测试方面也有 ...

  9. 2020年在项目中使用MVVM正确姿势,你用对了吗?

    最近看到了几篇与 Jetpack MVVM 有关到文章,使我不禁也想淌一下这场混水.我是在 2017 年下半年接触的 Jetpack 的那套开发工具,并且后来一直将其作为开发的主要框架.在这段时间的使 ...

  10. 闭嘴,给你一个数!1分钟,学完C语言指针,不扎手只扎心的针!

    序言 指针是C语言学习者绕不过的一道坎,也是C语言学习者不得绕过的一道坎.辨别一个人C语言学的好赖就看他对指针的理解怎么样.指针内容也是工作面试经常问到的问题.本文将带你重新认识那个绊倒你的指针,以解 ...