#include <bits/stdc++.h> using namespace std; #define fore(i,_a,_b) for(int i=(int)(_a);i<=(int)(_b);i++) #define forb(i,_a,_b) for(int i=(int)(_a);i>=(int)(_b);i--) #define fir first #define sec second #define SZ(a) (int)(a).size() #define pb push_back #define all(c) (c).begin(), (c).end() #define endl '\n' typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; const int INF=0x3f3f3f3f; map<int,int>mp; const int N=(int)2e5+5; int pre[N],nex[N]; int a[N]; bool is_unique(int p,int l,int r){ if(pre[p]<l && nex[p]>r) return true; return false; } bool check(int l,int r){ if(l>=r) return true; int mid=(r-l+1)>>1; fore(i,1,mid+1){ int lpos=l+i-1; if(is_unique(lpos,l,r)){ return check(l,lpos-1)&check(lpos+1,r); } int rpos=r-i+1; if(is_unique(rpos,l,r)){ return check(l,rpos-1)&check(rpos+1,r); } } return false; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int T;cin>>T; while(T--){ int n;cin>>n; fore(i,1,n) cin>>a[i]; mp.clear(); fore(i,1,n){ if(!mp.count(a[i])) pre[i]=-1; else pre[i]=mp[a[i]]; mp[a[i]]=i; } mp.clear(); forb(i,n,1){ if(!mp.count(a[i])) nex[i]=n+1; else nex[i]=mp[a[i]]; mp[a[i]]=i; } if(check(1,n)) cout<<"non-boring"<<endl; else cout<<"boring"<<endl; } return 0; }
确定整个区间是否每个子区间都有一个数字只出现一次,利用分治
注意优化:1.记录每个数字左右侧再次出现的位置,O(1)check
2.分治时,每次左右侧同时检查,这样防止出现每次都检查到最后再分治
启发式分治、折半分治