uva1608 non-boring sequences

We were afraid of making this problem statement too boring, so we
decided to keep it short. A sequence is called non-boring if its every
connected subsequence contains a unique element, i.e. an element such
that no other element of that subsequence has the same value. Given a
sequence of integers, decide whether it is non-boring . Input The rst
line of the input contains the number of test cases T . The
descriptions of the test cases follow: Each test case starts with an
integer n (1 n 200000) denoting the length of the sequence. In the
next line the n elements of the sequence follow, separated with single
spaces. The elements are non-negative integers less than 10 9 . Output
Print the answers to the test cases in the order in which they appear
in the input. For each test case print a single line containing the
word non-boring ' or boring ‘

用map预处理出每个位置的左边和右边最近的相等元素,从而可以在O(1)的时间内判断任意区间内某元素是否唯一。
对于一个区间l..r,从两边开始找唯一的元素p,找见之后只需要判断l..p-1和p+1..r是否都满足即可。
预处理复杂度O(nlogn),分治复杂度也是O(nlogn),所以总的时间复杂度O(nlogn)。
注意由于有的数据T比较大而n比较小,用memset的话会超时。

#include<cstdio>
#include<cstring>
#include<map>
#define M(a) memset(a,0,sizeof(a))
using namespace std;
int left[200010],right[200010],a[200010];
bool ok(int l,int r)
{
    if (l>=r) return 1;
    int i,j,k,x,y,z;
    for (i=l,j=r;i<=j;i++,j--)
    {
        if (left[i]<l&&right[i]>r) return ok(l,i-1)&&ok(i+1,r);
        if (left[j]<l&&right[j]>r) return ok(l,j-1)&&ok(j+1,r);
    }
    return 0;
}
int main()
{
    int i,j,k,m,n,p,q,x,y,z,T;
    scanf("%d",&T);
    while (T--)
    {
        map<int,int> mp; 
        scanf("%d",&n);
        for (i=1;i<=n;i++)
          scanf("%d",&a[i]);
        for (i=1;i<=n;i++)
        {
            if (mp.count(a[i]))
              left[i]=mp[a[i]];
            else
              left[i]=-1;
            mp[a[i]]=i;
        }
        mp.clear();
        for (i=n;i>=1;i--)
        {
            if (mp.count(a[i]))
              right[i]=mp[a[i]];
            else
              right[i]=n+1;
            mp[a[i]]=i;
        }
        if (ok(1,n)) printf("non-boring\n");
        else printf("boring\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值