UVA 1608:Non-boring sequences(递归+分治思想)

来源:互联网 发布:windows 8.1 远程桌面 编辑:程序博客网 时间:2024/06/14 11:46

Non-boring sequences

Time limit:3000 ms OS:Linux

点击查看题目内容

题意:

给出一个序列,如果他的任何一个连续的子序列都有至少一个特殊元素(在这个子序列中只出现一次),则这个序列是non-boring,否则是boring

解题思路:

首先要解决的问题是如何快速判断一个子序列是否有特殊元素,这里采用的办法是使用map记录下标为 i 的元素左边最近的相同元素的下标(设为l[i]),和右边最近的相同元素的下标(设为r[i])。
假设子序列的区间是[left,right],只要遍历其中的元素,看是否存在 l[i] < left 并且 r[i] > right 的,如果有就说明这个子序列是中存在特殊元素,就是第 i 个。
由这个特殊元素,我们可以得出[left,i+1],[left,i+2]……和[i-1,right],[i-2,right]……等区间的子序列都包含这个特殊元素。
由此,我们只需要证明[left,i-1]和[i+1,right]这两个区间也包含特殊元素,就可以推出[left,right]这个区间是non-boring了。
按照这个思路写出递归函数:

bool judge(int left,int right){    if(left>=right)        return true;    for(int i=left;i<=right;i++)    {        if(l[i]<left&&r[i]>right)            return judge(left,i-1)&&judge(i+1,right);    }    return false;}

看上去一点毛病都没有,但就是超时。看了大神的题解之后才知道原来可以 从两端同时遍历 i(而不是从单一的从左往右) ,这样就可以每次把子问题缩小一半的复杂度,从而优化时间。


Code:

#include <iostream>#include <algorithm>#include <map>#include <cstdio>using namespace std;const int maxn= 200000+5;int a[maxn];int l[maxn],r[maxn];map<int,int> m;int n;bool judge(int left,int right){    if(left>=right)        return true;    for(int i=0;i<=(right-left)/2;i++)    {        if(l[left+i]<left && r[left+i]>right)            return judge(left,left+i-1)&&judge(left+i+1,right);        if(l[right-i]<left && r[right-i]>right)            return judge(left,right-i-1)&&judge(right-i+1,right);    }    return false;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        for(int i=0;i<n;i++)            scanf("%d",a+i);        //记录第i个元素左边第一个相同元素的位置        m.clear();        for(int i=0;i<n;i++)        {            if(m.count(a[i]))                l[i]=m[a[i]];            else                l[i]=-1;            m[a[i]]=i;        }        //记录第i个元素右边第一个相同元素的位置        m.clear();        for(int i=n-1;i>=0;i--)        {            if(m.count(a[i]))                r[i]=m[a[i]];            else                r[i]=n;            m[a[i]]=i;        }        if(judge(0,n-1))            cout<<"non-boring"<<endl;        else            cout<<"boring"<<endl;    }    return 0;}
原创粉丝点击