感觉这题A得比较奇怪。。。
首先有一个很直接的想法是,对于一个点i,它所在的单独区间是
[prei,nxti]
,那么它将对
[prei,i−1]
与
[i+1,nxti]
的点的答案产生影响。如果把每个产生影响 的区间看做一个点,那么每个点i的影响就可以看做一个矩阵。显然就是看这些矩阵的并是否覆盖所有点。
写了之后发现WA了= =
懒得调= =
然后改了个奇怪的暴力
居然就A了
然而复杂度似乎不太对呢。。
同样对于一个区间
[prei,nxti]
,可以注意到对于横跨点i的区间一定是满足要求的,那么只需要检查i左边的区间和i右边的区间。至于是否有某个点i的区间覆盖当前区间,就从两边往中间找?
诶再仔细想想好像是可以卡掉的呢。出数据的时候再试试能不能把自己卡掉吧。
原来这题暴力的复杂度是对的!!!QAQ
whx问了糖老师,解的复杂度是
T(n)=max{T(k)+T(n−k)+min(n,n−k)}=O(nlogn)
whx给了个直观的证明:
http://whx991201.is-programmer.com/posts/190036.html
#include <bits/stdc++.h>
using namespace std;
#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 maxn 200007
#define maxs 800007
inline int rd() {
char c = getchar();
while (!isdigit(c)) c = getchar() ; int x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x;
}
typedef int arr[maxn];
typedef int seg[maxs];
int n;
arr pre , nxt , h , a;
map<int , int> exi;
void input() {
n = rd();
exi.clear();
rep (i , 1 , n) pre[i] = nxt[i] = 0;
rep (i , 1 , n) {
a[i] = rd();
if (!exi[a[i]])
pre[i] = 1;
else {
nxt[exi[a[i]]] = i - 1;
pre[i] = exi[a[i]] + 1;
}
exi[a[i]] = i;
}
rep (i , 1 , n) if (!nxt[i]) nxt[i] = n;
}
bool check(int l , int r) {
if (l >= r) return 1;
int _l = l , _r = r;
rep (i , l , r) {
int t = i & 1;
if (t) {
if (pre[_l] <= l && nxt[_l] >= r)
return check(l , _l - 1) && check(_l + 1 , r);
_l ++;
} else {
if (pre[_r] <= l && nxt[_r] >= r)
return check(l , _r - 1) && check(_r + 1 , r);
_r --;
}
}
return 0;
}
void solve() {
if (check(1 , n))
puts("non-boring");
else
puts("boring");
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
per (tt , rd() , 1) {
input();
solve();
}
return 0;
}