[分治] UVa1608 Non-boring sequences 不無聊序列 (分治與中途相遇法的結合)
阿新 • • 發佈:2019-01-07
題目
思路
1.主要思路:如果有一個只出現一次的元素A[p],那麼所有包含此元素的所有連續子序列都滿足不無聊。那麼只需分治判斷A[0~p-1]和A[p+1~n]是否不無聊即可。
2.分治方向的選擇:(上界分析)
- 從左往右找:最壞情況是唯一元素恰好在最右邊。
- 從右往左找:最壞情況是唯一元素恰好在最左邊。
- 從兩頭往中間找(中途相遇法):最壞情況是唯一元素恰好在最中間。
(此處其實有點類似快排的方法)
程式碼
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <map>
using namespace std;
const int maxn = 200000+10000;
int n, A[maxn], myprev[maxn], mynext[maxn];
map<int, int> cur;
void init(){
cur.clear();
for (int i = 0; i<n; i++){
if (!cur.count(A[i]))
cur[A[i]] = -1;
myprev[i] = cur[A[i]];
cur[A[i]] = i;
}
cur.clear();
for (int i = n-1; i>=0; i--){
if (!cur.count(A[i])){
cur[A[i]] = -1;
}
mynext[i] = cur[A[i]];
cur[A[i]] = i;
}
}
bool solve(int L, int R){
//printf("%d %d\n",L,R);
if (L == R-1 || L>=R) return true;
int i = L, j = R-1; //[i.j]
while(i<=j){
if (!(myprev[i] >= L && myprev[i] < R) && !(mynext[i] >= L && mynext[i] < R) && i<=j)
return solve(L,i) && solve(i+1,R);
i++;
if (!(myprev[j] >= L && myprev[j] < R) && !(mynext[j] >= L && mynext[j] < R) && i<=j)
return solve(L,j) && solve(j+1,R);
j--;
}
return false;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n); // scanf的輸入效率???
for(int i = 0; i<n; i++)
scanf("%d",&A[i]);
init();
if (solve(0,n)) printf("non-boring\n");
else printf("boring\n");
}
return 0;
}