Non-boring sequences(启发式分治)
题意:一个序列被称作是不无聊的,当且仅当,任意一个连续子区间,存在一个数字只出现了一次,问给定序列是否是不无聊的。
思路:每次找到一个只出现了一次的点,其位置的pos,那么继续分治[L,pos-1],[pos1+1,R];为了保证分治的复杂度,每次的复杂度应该是拆开后较小的哪个。
可以类比启发式合并。 所以我们应该从两头想中间找pos。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=200010; int a[maxn],pre[maxn],lat[maxn]; map<int,int>mp; bool check(int L,int R) { if(L>=R) return true; int l=L,r=R; rep(i,L,R){ if(i&1){ if(pre[l]<L&&lat[l]>R) return check(L,l-1)&&check(l+1,R); l++; } else { if(pre[r]<L&&lat[r]>R) return check(L,r-1)&&check(r+1,R); r--; } } return false; } int main() { int T,N; scanf("%d",&T); while(T--){ mp.clear(); scanf("%d",&N); rep(i,1,N) scanf("%d",&a[i]); rep(i,1,N){ lat[mp[a[i]]]=i; pre[i]=mp[a[i]]; mp[a[i]]=i; } rep(i,1,N) lat[mp[a[i]]]=N+1; if(check(1,N)) puts("non-boring"); else puts("boring"); } return 0; }
It is your time to fight!