Non-boring sequences(启发式分治)

与世无争的帅哥 提交于 2020-05-02 11:57:17

题意:一个序列被称作是不无聊的,当且仅当,任意一个连续子区间,存在一个数字只出现了一次,问给定序列是否是不无聊的。

思路:每次找到一个只出现了一次的点,其位置的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;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!