好吧,这道题的复杂度真是蛮神奇的。
http://whx991201.is-programmer.com/posts/190036.html
搞了好久才发现暴力的复杂度是对的。
首先处理出pre[i],nxt[i],很明显只要i这个位置的数如果pre[i]<L,nxt[i]>R那么这个数在区间[L,R]上只出现了一次。
考虑如果要检验区间[l,r],那么只需要找到一个在[l,r]上只出现了一次的数,然后把序列分成两部分分别检验就可以了。
但是我们不能直接按顺序找,而是要从两边往中间找,这样可以改变复杂度?
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #include<map> #define maxn 200010 using namespace std; map<int,int> p; int n,m,tot,T; int a[maxn],pre[maxn],nxt[maxn]; bool check(int L,int R) { if (L>=R) return 1; int l=L,r=R; for (int i=L;i<=R;i++) { if (i&1) { 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; } int main() { scanf("%d",&T); while (T--) { scanf("%d",&n); p.clear(); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); nxt[p[a[i]]]=i;pre[i]=p[a[i]]; p[a[i]]=i; } for (int i=1;i<=n;i++) nxt[p[a[i]]]=n+1; if (check(1,n)) printf("non-boring\n"); else printf("boring\n"); } return 0; }