序列

题目

在这里插入图片描述

数据范围

20% n ≤ \leq 100
100% n ≤ \leq 1000 , a[i] ≤ \leq 1e9

思路

  • 先拿20分吧,枚举删除的长度和左节点位置 ,然后再**O(n)**看是否合法即可。
  • 那么我们可以优化一下这个方法,显然如果删除长度为len的字串那么左右两边再多删几个,得到的序列也是合法的,所以我们可以二分优化一下。
  • 当然,也可以 n 2 n^2 n2枚举左右端点,记录剩余序列中有多少个不同的元素,以及每个元素的个数,在以此往后推右端点的时候可以直接减去当前元素数量,当没有不同元素时即可结束。
    细节方面可以离散化也可以打一个map

题外话

考场上花了1个多小时才写出来,真的蠢极了。想了一个算法

记录每个元素出现的第一个第二个倒数第二个倒数第一个位置,取min和max求一下长度。

后来被自己造的一组数据:1 3 2 1 2 4 3 4 hack了,就打了个暴力看数据后发现是正解,尽管还是因为标记数组没用map爆0(re)了,但是数据大点,我也要挂的。
呜呜呜,什么时候才能不这么蠢蛙。

代码

二分

int l=0,r=n;
while(l<=r)
{
	int mid=(l+r)>>1;
	if(check()) ans=mid,r=mid-1;
	else l=mid+1;
}
 

离散化(不去重)

const int N=1e5+10;
int a[N],b[N];
for(int i=1;i<=n;i++) a[i]=b[i]=read();
sort(b+1,b+1+n);
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+n,a[i])-b; 

离散化(去重)

const int N=1e5+10;
int a[N],b[N];
for(int i=1;i<=n;i++) a[i]=b[i]=read();
sort(b+1,b+1+n);
int tot=unique(b+1,b+1+n)-(b+1);
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+tot,a[i])-b; 

正解

	#include<bits/stdc++.h>
	using namespace std;
	int n,a[1010],flag=1;
	map<int,int> dic,b;
	int min1=100000,max1=-1000;
	int vis[100000];
	inline int read()
	{
		int Num=0,f=1; char ch=getchar();
		while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
		while(ch>='0'&&ch<='9') {Num=(Num<<1)+(Num<<3)+ch-'0'; ch=getchar();}
		return Num*f;
	}
	inline bool check(int r,int l)
	{
		for(int i=1;i<=n;i++) dic[a[i]]=0;
		for(int i=1;i<r;i++) 	
		{
		if(dic[a[i]]) return false;	
			dic[a[i]]++;
		}
		for(int i=l+1;i<=n;i++) 	
		{
			if(dic[a[i]]) return false;	
			dic[a[i]]++;
		}
		return true;
	}
	int main()
	{
		n=read();
		for(int i=1;i<=n;i++)
		{
			a[i]=read();
			b[a[i]]++;
			if(b[a[i]]>1) flag=0;
		} 
		if(flag) {puts("0"); return 0;}
		int l=0,r=n,ans=0;
		while(l<=r)
		{
			int len=(l+r)>>1,flag=1;
			for(int i=1;i+len<=n;i++) if(check(i,i+len)) ans=len,r=len-1,flag=0;
			if(flag) l=len+1;
		}
		cout<<ans+1;
		return 0;
	} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值