Uva-1608 Non-boring sequences(高效率算法)

185 篇文章 0 订阅
116 篇文章 0 订阅

题意:如果一个序列的任意连续子序列中至少有一个只出现一次的元素,则称这个序列是不无聊的.输入一个n(n <= 200000)个元素的序列A,判断它是不是无聊的.


分析:对一段序列[l,r]而言,我们先找到这整个序列中只出现了一次的元素,如果没有那么就可以直接返回false,假如我们得到了这个元素p,那么接下来只需要递归的去检查区间[l,p-1]和

[p+1,r]就行了,我们事先预处理出来每个元素前后最近相同元素的位置就可以o(1)的判断这个数字是不是在某个子序列中只出现了一次,这样我们可以扫一遍[l,r]来得到p.

设T(n)为规模为n时所需的时间,那么T(n) = max(T(p-1) + T(n-p) + O(n)),最坏情况下T(n) = O(n^2).但是如果我们从两边开始同步找p,复杂度就变成了T(n) = max(T(p-1)+T(n-p)+min(p,n-p)),最坏情况下每次p都在[l,r]中点,此时T(n) = 2*T(n/2) + O(n) = O(n*log(n)).


#include <bits/stdc++.h>
#define N 200005
using namespace std;
int T,n,a[N],pre[N],suc[N];
unordered_map<int,int> f;
bool jud(int l,int r)
{
    if(l >= r) return true;
    int flag = 0;
    int x = l,y = r;
    while(x <= y)
    {
        if(pre[x] < l && (!suc[x] || suc[x] > r))
        {
            flag = x;
            break;
        }
        if(pre[y] < l && (!suc[y] || suc[y] > r))
        {
            flag = y;
            break;
        }
        x++,y--;
    }
    if(!flag) return false;
    return jud(l,flag-1)&&jud(flag+1,r);
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        f.clear();
        scanf("%d",&n);
        for(int i = 1;i <= n;i++) scanf("%d",&a[i]);
        for(int i = 1;i <= n;i++)
        {
            pre[i] = f[a[i]];
            f[a[i]] = i;
        }
        f.clear();
        for(int i = n;i;i--)
        {
           suc[i] = f[a[i]];
           f[a[i]] = i;
        }
        cout<<(jud(1,n) ? "non-boring" : "boring")<<endl;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值