您的位置:首页 > 产品设计 > UI/UE

【bzoj4059】【Cerc2012】【Non-boring sequences】【分治】

2016-04-26 09:44 459 查看

Description

我们害怕把这道题题面搞得太无聊了,所以我们决定让这题超短。一个序列被称为是不无聊的,仅当它的每个连续子序列存在一个独一无二的数字,即每个子序列里至少存在一个数字只出现一次。给定一个整数序列,请你判断它是不是不无聊的。

Input

第一行一个正整数T,表示有T组数据。每组数据第一行一个正整数n,表示序列的长度,1 <= n <= 200000。接下来一行n个不超过10^9的非负整数,表示这个序列。

Output

对于每组数据输出一行,输出"non-boring"表示这个序列不无聊,输出"boring"表示这个序列无聊。

Sample Input

4

5

1 2 3 4 5

5

1 1 1 1 1

5

1 2 3 2 1

5

1 1 2 1 1

Sample Output

non-boring

boring

non-boring

boring

题解:

预处理出每个数的前一个位置和后一个位置.

对于一个数x它的位置是i,当l在[pre[i],i-1],r在[i+1,next[i]]之间时,[l,r]中x只出现过一次.

我们把每个x能产生贡献的区间放到二维平面上,显然是一个矩阵.

然后我们就可以扫描线+线段树处理.

这样会很慢.

正解是暴力.复杂度的证明非常神奇.

可以看这里:http://whx991201.is-programmer.com/posts/190036.html

代码:

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define N 210000
using namespace std;
map<int,int>point;
int pre
,next
,T,n,x,a
;
bool check(int l,int r){
int h=l,t=r;
if (l>=r) return 1;
for (int i=l;i<=r;i++)
if (i&1){
if (pre[h]<l&&next[h]>r) return check(l,h-1)&&check(h+1,r);
h++;
}
else{
if (pre[t]<l&&next[t]>r) return check(l,t-1)&&check(t+1,r);
t--;
}
return 0;
}
int main(){
scanf("%d",&T);
while (T--){
point.clear();
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%d",&x);
next[point[x]]=i;
pre[i]=point[x];
point[x]=i;a[i]=x;
}
for (int i=1;i<=n;i++) next[point[a[i]]]=n+1;
if (check(1,n)) puts("non-boring");
else puts("boring");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: