咱們懼怕把這道題題面搞得太無聊了,因此咱們決定讓這題超短。一個序列被稱爲是不無聊的,僅當它的每一個連續子序列存在一個獨一無二的數字,即每一個子序列裏至少存在一個數字只出現一次。給定一個整數序列,請你判斷它是否是不無聊的。php
4059: [Cerc2012]Non-boring sequences
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 632 Solved: 227Description
咱們懼怕把這道題題面搞得太無聊了,因此咱們決定讓這題超短。一個序列被稱爲是不無聊的,僅當它的每一個連續子序列存在一個獨一無二的數字,即每一個子序列裏至少存在一個數字只出現一次。給定一個整數序列,請你判斷它是否是不無聊的。php
Input
第一行一個正整數T,表示有T組數據。每組數據第一行一個正整數n,表示序列的長度,1 <= n <= 200000。接下來一行n個不超過10^9的非負整數,表示這個序列。node
Output
對於每組數據輸出一行,輸出"non-boring"表示這個序列不無聊,輸出"boring"表示這個序列無聊。ios
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 1Sample Output
non-boring
boring
non-boring
boringHINT
Source
鳴謝Tjzide
【分析】spa
這題我是不會往掃描線方向想的。感受很神奇。code
首先對於每一個a[i]求前一個同色的位置$last$和後一個的位置$next$,顯然左端點在[last+1,i]右端點在[i,next-1]的都是能夠的。xml
那麼把左端點當成x,右端點當成y,區間就表示成了平面上的一個點,可行區間集就是一個矩形,最後看看n個矩形是否把上三角覆蓋。blog
【這個把這題複雜化了,其實有更簡單的方法因此我沒打這個哦ip
很容易想到暴力。get
若是序列non-boring,一定有一個數值只出現了一次,找到他的位置i【可能有多個,先隨便找一個】,
那麼區間跨越i的均可以的嘛,因此只需判斷[l,i-1]和[i+1,r]便可。
就把區間分治了。
可是時間複雜度???
網上的神犇們說,從左右兩端向中間暴力枚舉,用$next$和$last$$O(1)$判斷便可。
是nlogn的。
由於:$T(n)=max{T(k)+T(n-k)+min(n,n-k)}=O(nlogn)$
直觀證實:
咱們考慮每一個對時間複雜度有貢獻的下標,它必定屬於兩段中比較小的那一段,因而。。
每次每一個下標被算一次,它的所在塊就會縮小一倍,那麼顯然每一個下標的貢獻就是O(logn),它的總時間複雜度就是O(nlogn)。
ORZORZ。。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 200010 8 9 struct node{int x,id;}t[Maxn]; 10 bool cmp(node x,node y) {return x.x<y.x;} 11 int a[Maxn],nt[Maxn],lt[Maxn],ft[Maxn]; 12 13 bool ffind(int l,int r) 14 { 15 if(l>=r) return 1; 16 int t=-1; 17 for(int i=0;i<=r-l+1;i++) 18 { 19 if(l+i>r-i) break; 20 if(nt[l+i]>r&<[l+i]<l) {t=l+i;break;} 21 if(nt[r-i]>r&<[r-i]<l) {t=r-i;break;} 22 } 23 if(t==-1) return 0; 24 return ffind(l,t-1)&&ffind(t+1,r); 25 } 26 27 int main() 28 { 29 int T; 30 scanf("%d",&T); 31 while(T--) 32 { 33 int n; 34 scanf("%d",&n); 35 for(int i=1;i<=n;i++) 36 { 37 scanf("%d",&t[i].x);t[i].id=i; 38 } 39 sort(t+1,t+1+n,cmp); 40 a[t[1].id]=1;int p=1; 41 for(int i=1;i<=n;i++) 42 { 43 if(t[i].x!=t[i-1].x) p++; 44 a[t[i].id]=p; 45 } 46 for(int i=1;i<=p;i++) ft[i]=n+1; 47 for(int i=n;i>=1;i--) nt[i]=ft[a[i]],ft[a[i]]=i; 48 for(int i=1;i<=p;i++) ft[i]=0; 49 for(int i=1;i<=n;i++) lt[i]=ft[a[i]],ft[a[i]]=i; 50 if(ffind(1,n)) printf("non-boring\n"); 51 else printf("boring\n"); 52 } 53 return 0; 54 }
2017-04-25 08:38:03