给你一个序列 判断里面有没有只出现过一次的元素
我们之前做过一道《唯一的雪花》(地址),那一次是利用滑动窗口找没有重复出现元素的子序列,这次我们用相同的思想找每个元素左边和右边最近的相同元素。因为当一个字符只出现过一次时,包含它的子串都是只出现一次的,然后就可以分治。
为了保护时间复杂度,要中途相遇,从两头向中间。
AC代码:
#include <iostream>
#include <map>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=200010;
int n;
int a[maxn],b[maxn],l[maxn],r[maxn];
map<int,int>lastl;
map<int,int>lastr;
bool solve(int L,int R)
{
if(L>=R) return true;
int i=L;
int j=R;
while(i<=j)
{
if(l[i]<L&&r[i]>R) return solve(L,i-1)&&solve(i+1,R);
if(l[j]<L&&r[j]>R) return solve(L,j-1)&&solve(j+1,R);
i++;
j--;
}
return false;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
lastl.clear();
lastr.clear();
for( int i=1,j=n;i<=n;i++,j--)
{
if(lastl[a[i]]==0) l[i]=-1;
else l[i]=lastl[a[i]];
lastl[a[i]]=i;
if(lastr[a[j]]==0) r[j]=0x3f3f3f3f;
else r[j]=lastr[a[j]];
lastr[a[j]]=j;
}
if(solve(1,n))
puts("non-boring");
else puts("boring");
}
return 0;
}