题意:如果一个序列的任意连续子序列中至少有一个只出现一次的元素,则称这个序列式为non-boring。输入一个n(n≤200000)个元素的序列A(各个元素均为109以内的非负整数),判断它是否无聊。
分析:
1、记录下每个元素左边和右边最近的与它值相同的元素的位置。
2、如果某个元素在某一序列中只出现过一次,那这个序列中所有包含该元素的子序列都是non-boring,因此只需要研究在这个序列中以该元素为分界线,其左边和右边的子序列是否无聊即可。
3、因为如果单独从左扫或从右扫,最坏情况可能是在右端或左端,所以从两边同时向中间扫。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define lowbit(x) (x & (-x)) const double eps = 1e-8; inline int dcmp(double a, double b){ if(fabs(a - b) < eps) return 0; return a > b ? 1 : -1; } typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1e9 + 7; const double pi = acos(-1.0); const int MAXN = 200000 + 10; const int MAXT = 10000 + 10; using namespace std; int a[MAXN], l[MAXN], r[MAXN]; map<int, int> mp; bool solve(int L, int R){ if(L >= R) return true; for(int i = 0; i <= (R - L) / 2; ++i){ if(l[L + i] < L && r[L + i] > R){ return solve(L, L + i - 1) && solve(L + i + 1, R); } if(l[R - i] < L && r[R - i] > R){ return solve(L, R - i - 1) && solve(R - i + 1, R); } } return false; } int main(){ int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); for(int i = 0; i < n; ++i){ scanf("%d", &a[i]); } mp.clear(); for(int i = 0; i < n; ++i){ if(!mp.count(a[i])) l[i] = -1; else l[i] = mp[a[i]]; mp[a[i]] = i; } mp.clear(); for(int i = n - 1; i >= 0; --i){ if(!mp.count(a[i])) r[i] = n; else r[i] = mp[a[i]]; mp[a[i]] = i; } bool ok = solve(0, n - 1); if(ok){ printf("non-boring\n"); } else{ printf("boring\n"); } } return 0; }
时间: 2024-10-11 12:38:32