Non-boring sequences(折半遞迴。。暫且這麼叫吧)
該題給一個序列,讓我們判斷是不是不無聊序列(如果不明白請看樣例), 我們可以將區間從大到小不斷壓縮來確定答案,首先要確定一個區間是否滿足要求,只要看這個區間裡是不是有一個只出現一次的數,受前面《唯一的雪花》一題的啟發,我們可以在O(n)時間內求出當前數離他最近的與他相同的數的位置,用陣列儲存,那麼可以在O(1)的時間快速判斷,這樣就將時間複雜度降到O(n^2) 但是這樣還是不夠的,會超時。
紫書上給出了一個很巧妙的方法,那就是在遞迴的時候折半列舉 , 時間複雜度變成了 T(n) = 2*T(n/2) + O(n) 。 讓我們變一下形式,T(n)/n = T(n/2)/(n/2) + 2; 令T(n)/n = C(n);
則C(n) - C(n/2) = 2; 令n = 2^k; 則令k = 1,2,3..... 然後累加就得到 C(2^k) = C(1) + 2*k ,所以C(n) = C(1)+ 2*logn (以2為底) 所以時間複雜度是n*logn
這個公式叫主定理,大家可以自己查閱。
#include<bits/stdc++.h> using namespace std; const int maxn = 200000+5; int T,n,a[maxn],pre[maxn],nex[maxn]; map<int,int> cur ; bool is_unique(int p,int l,int r){ return pre[p]<l&&nex[p]>r; } bool check(int l,int r){ if(l>=r) return true; for(int i=l;i-l<=r-i;i++){ //折半遞迴 if(is_unique(i,l,r)){ return check(i+1,r)&&check(l,i-1); } if(is_unique(r-i+l,l,r)) return check(r-i+l+1,r)&&check(l,r-i+l-1); } return false; } int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); cur.clear(); for(int i=0;i<n;i++){ if(!cur.count(a[i])) pre[i] = -1; else pre[i] = cur[a[i]]; cur[a[i]] = i; } cur.clear(); for(int i=n-1;i>=0;i--){ if(!cur.count(a[i])) nex[i] = n; else nex[i] = cur[a[i]]; cur[a[i]] = i; } if(check(0,n-1)) printf("non-boring\n"); else printf("boring\n"); } return 0; }
相關推薦
Non-boring sequences(折半遞迴。。暫且這麼叫吧)
該題給一個序列,讓我們判斷是不是不無聊序列(如果不明白請看樣例), 我們可以將區間從大到小不斷壓縮來確定答案,首先要確定一個區間是否滿足要求,只要看這個區間裡是不是有一個只出現一次的數,受前面《唯一的雪花》一題的啟發,我們可以在O(n)時間內求出當前數離他最近的與他相同的數
UVA 1608 Non-boring sequences (分冶+遞歸)
iostream col 容易 不存在 ons mage 搜索 pos 子序列 一、題目概述 二、題目釋義 要求序列s的所有子序列,若所有這些子序列中均存在一個自己序列內是唯一的數,則稱這個序列s是不無聊的 三、思路分析 從序列s開始考慮,序列s的整個長度為n,若序列s中
【bzoj 4059】Non-boring sequences(分治+啟發式分裂)
傳送門biu~ 我們可以把相同的數字用雙向連結串列串起來,pre[x]為x位置之前第一個和x位置數字相同的位置,nexxnexx為xx位置之後第一個和xx位置數字相同的位置。對於區間[l,r][l,r
UVA - 1608 Non-boring sequences(分治法)
name 表示 urn its mes else pac 學習 tro 題目: 如果一個序列的任意連續的子序列中至少有一個只出現一次的元素,則稱這個序列是不無聊的。輸入一個n(n≤200000)個元素的序列A(各個元素均為109以內的非負整數),判斷它是不是不無聊的。 思路
二叉樹遍歷演算法(遞迴實現先序中序和後續遍歷)(非遞迴實現中序和先續)
二叉樹遍歷 這兩天抓緊把二叉樹遍歷複習了一遍,遞迴實現還是一如既往地簡潔,迭代版本寫了好久還是隻實現了先序和中序,後續一直沒搞明白,有空了再更新。 遞迴實現 void RecursionBackTree(TreeNode * root) {
【高效演算法設計——遞迴】 UVa 1608 Non-boring sequences
題意:給定一段序列,如果這段序列的任意連續子序列中至少存在一個數唯一,那麼這段序列就是Non-boring,否則就是boring,判定這段序列是否boring 思路:如果一個數A[x]是全場唯一,那麼我們只需判斷A[1]~A[x-1] 和A[x+1]~A[n]是否滿足要求
折半查詢(非遞迴)
設有n個數據儲存於有序資料表中,在進行折半查詢之前,先找出資料表中的正中元素的下標mid,利用其關鍵碼L.Data[mid]與定值x作比較。 若x.key=L.Data[mid].key,查詢成功,返回其下標mid並報告成功; &nb
[分治] UVa1608 Non-boring sequences 不無聊序列 (分治與中途相遇法的結合)
題目 思路 1.主要思路:如果有一個只出現一次的元素A[p],那麼所有包含此元素的所有連續子序列都滿足不無聊。那麼只需分治判斷A[0~p-1]和A[p+1~n]是否不無聊即可。 2.分治方向的選擇:(上界分析) 從左往右找:最壞情況是唯一元素恰好在
(1)建立二叉樹的二叉連結串列。 (2)寫出對用二叉連結串列儲存的二叉樹進行先序、中序和後序遍歷的遞迴和非遞迴演算法。 (3)寫出對用二叉連結串列儲存的二叉樹進行層次遍歷演算法。 (4)求二叉樹的所有葉子及結點總數。
(1)建立二叉樹的二叉連結串列。 (2)寫出對用二叉連結串列儲存的二叉樹進行先序、中序和後序遍歷的遞迴和非遞迴演算法。 (3)寫出對用二叉連結串列儲存的二叉樹進行層次遍歷演算法。(4)求二叉樹的所有葉子及結點總數。 include<stdio.h> #inclu
●UVA 1608 Non-boring sequences
and bsp auth IT include ide 表示 bool targe 題鏈: https://vjudge.net/problem/UVA-1608#author=chenchonghan題解: 分治 如果一個區間[l,r]裏面在p位置出現了一個只出現一次
bzoj4059 [Cerc2012]Non-boring sequences
分治 過程 == break 掃描線 sequence 合並 algo 檢驗 根本不會。。。 似乎有很高妙的分治做法啊!https://www.cnblogs.com/forever97/p/bzoj4059.html 就是說,如果當前區間為[l,r],有一個i滿足pr
uva1608 Non-boring sequences
nlogn break 序列 lse uva next 復雜度 pri span 某個序列找到唯一元素後,判斷被分成的兩邊的序列即可問題在於找到唯一元素連續序列,重復元素的問題;感覺很有一般性 查找相同元素用map,last,next存上一個相同元素的位置復雜度計算有點思
【資料結構】二叉樹的建立和遍歷(非遞迴)
該程式使用的是遞迴地建立方法,以及非遞迴的遍歷演算法 執行環境:Dev-C++ #include <stdio.h> #include <stdlib.h> typedef struct node{ char data; struct node *lchild
洛谷P1192臺階問題(單向遞迴dfs,逆向遞迴記憶化)
題目連結:https://www.luogu.org/problemnew/show/P1192 題目很有價值,用搜索寫的話,可以加深對遞迴搜尋的理解。一般這樣的遞推可以用:dp或記憶化(我就用記憶化了 記憶化一般有遞推規律(遞迴好寫就在這),適用於遞推題!數範圍略大題!一般逆向遞迴dfs
二叉樹----資料結構:二叉樹的三種遍歷,利用遞迴演算法。
二叉樹----資料結構:二叉樹的三種遍歷,利用遞迴演算法。 魯迅:總之歲月漫長,然而值得等待。 #define CHAR /* 字元型 */ /* #define INT /* 整型(二者選一) */ #
hdu 1007 Quoit Design (分治+遞迴)
題意就是輸入一堆點在二維平面上的座標,找出距離最短的兩個點對,距離除以2輸出。 很簡單的遞迴加分治。然而我昨天寫的時候WA到心態爆炸,今天終於明白整個結構都有問題,重新修改了一遍,直接過了。 附上程式碼: #include<iostream> #include<cs
[Cerc2012]Non-boring sequences
Description 定義一個序列是不無聊的,當且僅當它的所有子區間都存在一個獨一無二的數字,即每個子區間裡至少存在一個數字只出現過一次。給定一個長度為\(N(N\leq2\times 10^5)\)的序列,請判斷它是不是無聊的。 Solution 對於每個位置\(i\),先求出\(pre[i],nx
線索化二叉樹(附三種非遞迴方式遍歷二叉樹)
資料結構二叉樹這快學的雲裡霧裡,所以就寫歌c++樹的類來將這寫東西全部封裝起來,想用那個直接呼叫方法,我決免費將這個大類提供給大家,提供學習上的參考,少走彎路,由於程式碼比較多,我就將各方法的功能做了註釋,如果那有什麼不懂的,可以交流。線面就是原始碼了~~~ tree.h #ifnd
圖的深度優先遍歷(非遞迴+遞迴,詳解)
圖的深度優先遍歷 非遞迴演算法: #include<iostream> #include<stack> using namespace std; const int MaxSize=100; class MGraph{//鄰接矩陣的構建 p
python 學習彙總36:遞迴函式(尾遞迴)( tcy)
遞迴函式(尾遞迴) 2018/11/15 用途: 遞迴函式常用於檢索大量資料,替代for迴圈。 1.遞迴深度設定: sys.getrecursionlimit() #返回