题目大意:
给出一个N长度的数字序列,对于任一子序列中,都存在唯一不重复出现的数字,则称为不无聊序列,否则为无聊序列。
思路:
如果某个数字a[i]在序列中只出现一次,那么任何包含a[i]的序列都是不无聊的,则只需要考虑i-1的序列和i+1的序列是否满足。以此类推,递归下去。
问题则转变成判断某个数字在某子序列中是否唯一。方法是用l[i],r[i]两个数组分别记录总序列中第i个元素左边和它相等的最近的位置坐标和右边和它相等的最近的位置坐标。
在查找时为了避免极端情况,可以分别从1->n和n->1遍历查找。
附上AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 5;
int ln[maxn], rn[maxn];
int e[maxn];
map<int, int> _m;
int T, n;
int uniq(int t, int l, int r) {
return ln[t] < l && rn[t] > r;
}
int check(int l, int r) {
if(l >= r) return 1;
for(int i = 0; l + i <= r - i; i++) {
if(uniq(l + i, l, r)) return check(l + i + 1, r) && check(l, l + i - 1);
if(uniq(r - i, l, r)) return check(l, r - i - 1) && check(r - i + 1, r);
}
return 0;
}
int main() {
ios :: sync_with_stdio(false);
cin >> T;
while(T--) {
cin >> n;
for(int i = 0; i < n; i++) {
cin >> e[i];
}
//由左向右遍历
_m.clear();
for(int i = 0; i < n; i++) {
if(!_m.count(e[i]) ) ln[i] = -1;
else ln[i] = _m[e[i] ];
_m[e[i] ] = i;
}
//由右向左遍历
_m.clear();
for(int i = n - 1; i >= 0; i--) {
if(!_m.count(e[i]) ) rn[i] = n;
else rn[i] = _m[e[i] ];
_m[e[i] ] = i;
}
if(check(0, n - 1) )
cout<<"non-boring"<<endl;
else
cout<<"boring"<<endl;
}
return 0;
}