题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4483
题目大意:给一个序列,问这个序列无不无聊,不无聊序列的定义是任意的连续序列中都能找到一个只出现过一次的数字
题目思路:首先给一个序列,这个序列中满足有一个只出现过一次的数字,那么,在这个序列中,所有跨过这个数字的区间一定都是不无聊的,所以想出现无聊的数字一定得在两边找,那么就可以想到利用分治。然后使用map帮助记录每个数字前一个离它最近的与它相同的值的位置,以及后一个离它最近的与它相同值的位置。如果左边的小于当前分治区间的左位置,右边大于,那么在这个区间内他就只出现过一次,继续分治,如果找不到那就说明凉了
这题有个要注意的就是要左边右边一起找,否则会超时
以下是代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
const int MAXN=2e5+5;
const int MOD =1e9+7;
int n,a[MAXN],l[MAXN],r[MAXN];
unordered_map<int,int>mp;
bool solve(int posl,int posr){
if(posl>=posr)return 1;
int L=posl,R=posr;
while(L<=R){
if(l[L]<posl&&r[L]>posr)return solve(posl,L-1)&&solve(L+1,posr);
if(l[R]<posl&&r[R]>posr)return solve(posl,R-1)&&solve(R+1,posr);
L++;R--;
}
return 0;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
mp.clear();
scanf("%d",&n);
rep(i,1,n){
scanf("%d",&a[i]);
if(!mp.count(a[i])){
l[i]=0;
}
else{
l[i]=mp[a[i]];
}
mp[a[i]]=i;
}
mp.clear();
per(i,n,1){
if(!mp.count(a[i])){
r[i]=n+1;
}
else{
r[i]=mp[a[i]];
}
mp[a[i]]=i;
}
if(solve(1,n)){
puts("non-boring");
}
else{
puts("boring");
}
}
return 0;
}