【问题描述】
一个序列被称为有趣的序列是它的所有的子串拥有一个唯一的整数(这个整数在整个序
列中只出现过一次)。
给你一个序列的整数, 问你它是否是有趣的。
【输入格式】
第一行 T, 表示数据组数。
接下来每组数据第一行一个 n。
接下来是 n 个整数, 均小于 10^9。
【输出格式】
输出 boring 或者 non-boring。
【输入样例】
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
【输出样例】
non-boring
boring
non-boring
boring
【数据范围与约定】
对于 30%的数据: n<=10。
对于 100%的数据: n <= 200000, 每个整数小于 10^9。
ps: 子串为一个连续的区间。
下面的题解是PPT里的官方题解
100分:优秀的暴力。对于一个a[i],前一次出现记为pre[i],后一次出现记为nex[i]。那左端点l在pre[i]+1..i,右端点在i..nex[i]-1都是合法的。如果判定一个区间[l,r],a[i]是其中唯一出现过的数字。那这个区间就可以切割成判定2个区间[l,i - 1],[i + 1, r]。那对于一个区间[l,r],i,j同时从左边和右边开始扫,碰到第一个唯一出现的数字就切割。直到l>=r。这种做法看起来很像暴力,但实际上跑得飞快。时间复杂度证明:T(n) = T(k) + T(n-k)+min(n, n - k)。一种直观的想法就是,每次复杂度都是较小的那个区间。倒过来看相当于较小的合并到较大的。那就是启发式合并。O(nlogn)。
然后下面是自己的话:
昨天 小奇的糖果 里我好像说过遇到这种有不同颜色的东西经常把相同颜色的用双向链表串起来,结果早上模拟考时还是没有这样操作(只写了30分暴力)
早上的暴力程序还因为 boring 打成了 borning 结果30分都没拿到(!) 失望~~ (下次一定要注意)
直接贴代码好了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 7 #define For(i,a,b) for(register int i=a;i<=b;++i) 8 #define Dwn(i,a,b) for(register int i=a;i>=b;--i) 9 #define Re register 10 11 using namespace std; 12 13 const int N=2e5+10; 14 int Ld[N],Rd[N],a[N],lst[N]; 15 struct LIS{ 16 int x,id; 17 }Lis[N]; 18 int n,m,x,y; 19 inline void read(int &v){ 20 v=0; bool fg=0; 21 char c=getchar(); if(c=='-')fg=1; 22 while(c<'0'||c>'9'){c=getchar(); if(c=='-')fg=1;} 23 while(c>='0'&&c<='9'){v=v*10+c-'0',c=getchar(); if(c=='-')fg=1;} 24 if(fg)v=-v; 25 } 26 bool cmp(const LIS &a,const LIS&b){ 27 return a.x<b.x; 28 } 29 30 bool Trial(int l,int r){ 31 if(l>=r)return 0; 32 int pl=l,pr=r; 33 int ppl=l,ppr=r; 34 35 bool fail=0,nxfail=0; 36 while(pl<=pr){ 37 fail=0; 38 if(Ld[pl]<ppl&&Rd[pl]>ppr){ 39 fail=1; 40 if(Trial(ppl,pl-1))return 1; 41 ppl=pl+1; nxfail=0; 42 pr=ppr; 43 } 44 45 pl++; 46 if(pl>pr)break; 47 fail=0; 48 if(Ld[pr]<ppl&&Rd[pr]>ppr){ 49 fail=1; 50 if(Trial(pr+1,ppr))return 1; 51 ppr=pr-1; nxfail=0; 52 pl=ppl; 53 } 54 pr--; 55 if(pl>pr)break; 56 57 } 58 if(fail)return 0; 59 else return 1; 60 } 61 62 int main(){ 63 freopen("seq.in","r",stdin); 64 freopen("seq.out","w",stdout); 65 int T; 66 read(T); 67 while(T--){ 68 memset(lst,0,sizeof(lst)); 69 memset(Ld,0,sizeof(Ld)); 70 memset(Rd,0,sizeof(Rd)); 71 read(n); 72 For(i,1,n)read(Lis[i].x),Lis[i].id=i; 73 sort(Lis+1,Lis+n+1,cmp); 74 Lis[0].x=-2147483600; 75 int tt=0; 76 For(i,1,n){ 77 if(Lis[i].x!=Lis[i-1].x)tt++; 78 int ID=Lis[i].id; 79 a[ID]=tt; 80 } 81 For(i,1,n){ 82 int ax=a[i]; 83 int prD=lst[ax]; 84 Ld[i]=prD; Rd[i]=n+1; 85 if(prD)Rd[prD]=i; 86 lst[ax]=i; 87 } 88 if(Trial(1,n)){ 89 printf("boring "); 90 }else{ 91 printf("non-boring "); 92 } 93 } 94 fclose(stdin); fclose(stdout); 95 return 0; 96 }