1. 程式人生 > >Non-boring sequences(折半遞迴。。暫且這麼叫吧)

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() #返回