Codeforces Round #765 (Div. 2) 1625B Elementary Particles

题目描述(传送门

在这里插入图片描述

题目翻译:

对于序列(a1,a2,…,an),可以用(al,al+1,…,ar)来表示其子序列,其中l表示左边界,r表示有边界(1 ≤ l ≤ r ≤ n)。比如对于序列(1 4 2 8 5 7)及边界l = 2, r = 4,则子序列为(4 2 8)。当两个序列的l和r中有一个不相同时,两个序列就被认为是不相同的序列。
注意,即使两个子序列的元素相同且排列顺序一样,但只要l和r有一个不相同,两个子序列就是不相同的。比如有序列(1 1 1 1 1)以及两个子序列:l=1,r=3和l=2,r=4。虽然两个子序列的内容都是(1 1 1),但是这两个子序列是不相同的,因为它们的l,r不一样。
现在你需要从一个序列中找出两个长度均为k的子序列(可存在重叠部分)。但是这两个子序列必须是harmonious(和谐的?),即对于某些下标i(1≤i≤k),两个子序列的第i个元素必须相同。比如(1 7 3)和(4 7 8)是harmonious的,因为第2个元素都是7。而(1 2 3)和(3 1 2)不是harmonious的。
请你求出满足上述条件(1、两个子序列的l或r不相同;2、harmonious)的两个子序列的最大长度。

解题思路:

首先可以确定的是,两个子序列只要有一个位置的元素相同即可。题目又要求两个子序列在原序列的位置不能完全重合,则我们需要在原序列中找到两个相同的元素,再分别以这两个元素为基准,找到尽可能长的两个等长的子序列。如果我们找到了两个相同元素的位置,怎么确定子序列的长度呢?比如序列(1 2 3 4 5 6 7 3 9),可以找到两个3,那么子序列的长度显然是3+1=4,懂的话可以跳过下面的啰嗦

暂且抛开题目的限制,设两个子序列为(1 2 3 4 5 6 7 3 9)、(1 2 3 4 5 6 7 3 9)。然后开始加题目的限制,为使两个3的下标一致,则第二个子序列需要删去前面的1 2 3 4 5,注意子序列是连续的,则两个子序列变为(1 2 3 4 5 6 7 3 9)、(6 7 3 9)。为使两个子序列长度相同,则需要删除第一个序列后面的5个元素,两个子序列变为(1 2 3 4 )、(6 7 3 9),最后子序列的长度就是4。

简单地说就是第一个3的位置决定子序列的前半段长度,第二个3决定子序列的后半段长度,即ans=i+n-j=n-(j-i),其中i是第一个元素的下标,j是第二个元素的下标,i<j,n是原序列长度
那么在什么情况下,子序列的长度才最长呢?通过上面的公式ans=n-(j-i) 可以知道,当j-i最小时,结果最大,即两个元素越接近,子序列长度越长。而与两个元素具体是在原序列的中间还是一端没有关系,当时的我就是下意识地认为越中间越好,而忽略了关键是要两个元素尽可能地靠近。

代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 200010
using namespace std;
int main(){
//	freopen("1.txt","r",stdin);
	int t,n,l,r,book[N],a,maxn,d;
	cin>>t;
	while(t--){
		cin>>n;
		memset(book,0,sizeof(book));
		maxn=-1;
		for(int i=1;i<=n;i++){
			cin>>a;
			if(book[a]==0) book[a]=i;//如果这个数字是第一次出现,则标记其位置
			else{//不是第一个出现
				//book[a]是这个数字上一次出现的位置,book[a]+n-i等同于上面分析中的ans=i+n-j
				maxn=max(maxn,book[a]+n-i);
				//更新位置。因为只考虑最接近的两个数字,所以只需要保存该数字上一次出现的位置,而不管再之前的
				book[a]=i;
			}
		}
		cout<<maxn<<endl; 
	}

	return 0;
}
总结:

正确分析更重要,不要没想明白就开始敲代码。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值