【bzoj 4059】Non-boring sequences

13 篇文章 0 订阅
1 篇文章 0 订阅

传送门~

解题思路

考虑分治。虽然我觉得就是暴力
对于一个数,左边第一个与它一样的数的位置记为z[i],右边第一个记为y[i]。
对于区间[l,r],如果其中存在一个数i,使z[i] < l 并且 y[i] > r,那么区间[l,r]是一定符合题目中条件的,只要这个区间的子区间[l,i-1]和[i+1,r]也符合条件,区间[l,r]就是不无聊的。于是这么分治下去就行了。
但是这么写会T,确切的说会被卡成 O (n2)。
在区间[l,r]中枚举 i 的时候,从两边向中间找,这样枚举下来就成了 O (nlogn)了。

上午发的这篇博客,但是并不清楚复杂度是怎么证的,然而下午就被zP1nG大佬证出来了%%%
如果每次从左向右枚举,就可能每层要找的i都在最左边或最右边,这样每层都要枚举n次,而且要跑n层递归,这样就会变成 n2
但是如果每次从两边向中间枚举,就不会扫遍整个序列。最坏的情况是i在序列中间,这时候就会在每一层跑满n次,但因为每次序列长度都除以2,所以最多log层,合起来就是最坏 O (nlogn)了。

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;
int sh[200005],xi[200005];
int hed[200005];
int s[200005],b[200005];
int n,T;
bool check(int x,int y){
    if(x>y) return 1;
    int lx=x,ly=y;

    while(lx<=ly){
        if(sh[lx]<x && xi[lx]>y) 
        return check(x,lx-1) && check(lx+1,y);
        lx++;
        if(sh[ly]<x && xi[ly]>y)
        return check(x,ly-1) && check(ly+1,y);
        ly--;
    }

    return 0;
}
int main(){
    scanf("%d",&T);
while(T--){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i]);
        b[i]=s[i];hed[i]=0;
    }
    sort(b+1,b+n+1);
    int top=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++) s[i]=lower_bound(b+1,b+top+1,s[i])-b;
    for(int i=1;i<=n;i++){
        sh[i]=hed[s[i]];
        hed[s[i]]=i;
    }
    for(int i=1;i<=n;i++) hed[i]=n+1;
    for(int i=n;i>=1;i--){
        xi[i]=hed[s[i]];
        hed[s[i]]=i;
    }
    if(check(1,n)) printf("non-boring\n");
    else printf("boring\n");    
}
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值