[cerc2012][Gym100624D]20181013

 

题意:一个序列,如果存在一个连续子序列,满足该子序列中没有只存在一次的序列,则原序列为boring,否则non-boring

 

题解:

分治递归

对一个序列,如果找到了一个只出现一次的数位于a[x],则问题转化为子序列a[1]...a[x-1]和a[x+1]..a[len]这两个序列有没有boring序列,故分治。

判断a[x]是否是在这个数列中只出现一次:记录左边最近一次出现a[x]的位置l[x],右边为r[x],若数列为a[L]...a[R],则l[x]<L&&r[x]>R

找a[x]:

从两边向中间找,最坏情况为每次从两边找到中间,T(n)=T(n/2)+O(n) --> O(nlogn)
从中间向两边找,最坏情况为每次从中间找到两边,T(n)=T(n-1)+O(n) --> O(n^2)

 1 /*
 2 从两边向中间找,最坏情况为每次从两边找到中间,T(n)=T(n/2)+O(n) --> O(nlogn)
 3 从中间向两边找,最坏情况为每次从中间找到两边,T(n)=T(n-1)+O(n) --> O(n^2)
 4 */
 5 
 6 #include<cstdio>
 7 #include<cstdlib>
 8 #include<cstring>
 9 #include<iostream>
10 #include<algorithm>
11 #include<cmath>
12 #include<queue>
13 #include<vector>
14 #include<ctime>
15 using namespace std;
16 
17 const int N=200010;
18 int a[N],l[N],r[N],id[N];
19 struct node{
20     int d,id;
21 }p[N];
22 
23 bool cmp(node x,node y){return x.d<y.d;}
24 
25 bool find_one(int L,int R)
26 {
27     if(L>R) return 0;
28     int mid=(L+R)/2;
29     int t=0,x;
30     for(int i=0;;i++)
31     {
32         if(L+i<=R && l[L+i]<L && r[L+i]>R) return find_one(L,L+i-1) || find_one(L+i+1,R);
33         if(R-i>=L && l[R-i]<L && r[R-i]>R) return find_one(L,R-i-1) || find_one(R-i+1,R);
34         if(L+i>R && R-i<L) break;
35     }
36     /*
37     //从中间向两边找 tle
38     while(mid+t<=R || mid-t>=L)
39     {
40         if(mid+t<=R) 
41         {
42             x=mid+t;
43             if(l[x]<L && r[x]>R) return find_one(L,x-1) || find_one(x+1,R);
44         }
45         if(mid-t>=L)
46         {
47             x=mid-t;
48             if(l[x]<L && r[x]>R) return find_one(L,x-1) || find_one(x+1,R);
49         }
50         t++;
51     }
52     */
53     return 1;
54     
55 }
56 
57 int main()
58 {
59     //freopen("a.in","r",stdin);
60     int n,T;
61     scanf("%d",&T);
62     while(T--)
63     {
64         scanf("%d",&n);
65         
66         for(int i=1;i<=n;i++)
67         {
68             scanf("%d",&a[i]);
69             p[i].d=a[i];
70             p[i].id=i;
71         }
72         sort(p+1,p+1+n,cmp);
73         int pre=-1,num=0;
74         for(int i=1;i<=n;i++)
75         {
76             if(p[i].d!=pre) num++;
77             pre=p[i].d;
78             a[p[i].id]=num;
79         }
80         memset(id,0,sizeof(id));
81         for(int i=1;i<=n;i++)
82         {
83             l[i]=id[a[i]];
84             id[a[i]]=i;
85         }
86         for(int i=1;i<=n;i++) id[a[i]]=n+1;
87         for(int i=n;i>=1;i--)
88         {
89             r[i]=id[a[i]];
90             id[a[i]]=i;
91         }
92         if(find_one(1,n)) printf("boring\n");
93         else printf("non-boring\n");
94     }
95     return 0;
96 }

 

posted @ 2018-10-18 11:57  拦路雨偏似雪花  阅读(174)  评论(0编辑  收藏  举报