UVa 1608 (分治 中途相遇) Non-boring sequences
预处理一下每个元素左边和右边最近的相邻元素。
对于一个区间[l, r]和区间内某一个元素,这个元素在这个区间唯一当且仅当左右两边最近的相邻元素不在这个区间内。这样就可以O(1)完成查询。
首先查找整个字符串是否有唯一元素,如果没有则整个序列是无聊的。
有的话,假设这个唯一元素下标是p,那么如果子序列[0, p-1]和[p+1, n-1]是不无聊的,那么这个序列就是不无聊的。
关于查找的话,如果只从一端查找唯一元素,最坏的情况就是O(n)。所以可以从两端进行查找,总的时间复杂度是O(nlogn)。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 200000 + 10; 5 int a[maxn], L[maxn], R[maxn]; 6 7 map<int, int> cur; 8 9 inline bool ok(int pos, int l, int r) 10 { return L[pos] < l && R[pos] > r; } 11 12 bool solve(int l, int r) 13 { 14 if(l >= r) return true; 15 for(int i = 0; l+i <= r-i; i++) 16 { 17 if(ok(l+i, l, r)) return solve(l, l+i-1) && solve(l+i+1, r); 18 else if(ok(r-i, l, r)) return solve(l, r-i-1) && solve(r-i+1, r); 19 } 20 return false; 21 } 22 23 int main() 24 { 25 //freopen("in.txt", "r", stdin); 26 27 int T; scanf("%d", &T); 28 while(T--) 29 { 30 int n; scanf("%d", &n); 31 for(int i = 0; i < n; i++) scanf("%d", &a[i]); 32 cur.clear(); 33 for(int i = 0; i < n; i++) 34 { 35 L[i] = cur.count(a[i]) ? cur[a[i]] : -1; 36 cur[a[i]] = i; 37 } 38 cur.clear(); 39 for(int i = n-1; i >= 0; i--) 40 { 41 R[i] = cur.count(a[i]) ? cur[a[i]] : n; 42 cur[a[i]] = i; 43 } 44 45 printf("%s\n", solve(0, n-1) ? "non-boring" : "boring"); 46 } 47 48 return 0; 49 }