1. 程式人生 > >NOIP複賽複習(八)STL演算法與樹結構模板

NOIP複賽複習(八)STL演算法與樹結構模板

STL演算法

STL 演算法是一些模板函式,提供了相當多的有用演算法和操作,從簡單如for_each(遍歷)到複雜如stable_sort(穩定排序),標頭檔案是:#include <algorithm>。常用STL 演算法庫包括:sort快速排序演算法、二分查詢演算法、列舉排列演算法等。


1 sort排序系列

sort對給定區間所有元素進行排序(全排)
stable_sort對給定區間所有元素進行穩定排序,就是相等的元素位置不變,原來在前面的還在前面。
partial_sort對給定區間所有元素部分排序,就是找出你指定的數目最小或最大的值放在最前面或最後面,比如說我只要找到

1000000個數中最大的五個數,那你用這個函式是最好的,排序後最大的五個數就在最前面的五個位置,其他的元素位置分佈不確定。
partial_sort_copy對給定區間複製並排序,和上面的一樣,只是這是指定區間進行復制然後排序的。
nth_element找出給定區間的某個位置對應的元素,根據比較函式找到第n個最大(小)元素,適用於尋找n個元素
is_sorted判斷一個區間是否已經排好序(返回bool值判斷是否已排序)
partition使得符合某個條件的元素放在前面,劃分區間函式,將 [first, last]中所有滿足的元素置於不滿足的元素前面,這個函式會返回迭代器,設返回的迭代器為
 i,則對 [first, i]中的任意迭代器 j*j滿足給定的判斷,對 [i, last] 中的任意迭代器 k*k不滿足。
stable_partition相對穩定的使得符合某個條件的元素放在前面(和上面的一樣,只是位置不變)

使用時根據需要選擇合理的排序函式即可,所有的排序函式預設從小到大排序,可以定義自己的比較方式。

 

2、二分系列

二分檢索,複雜度O(log(last-first))
itr =upper_bound(first, last, value, cmp);
//itr 

指向大於value 的第一個值(或容器末尾)
itr = lower_bound(first, last, value, cmp);
//itr 
指向不小於valude 的第一個值(或容器末尾)
pairequal_range(first, last, value, cmp);
//
找出等於value的值的範圍O(2*log(last–first))
Binary_search(first,last, value)
返回bool值,找到則true,否則false

二分經常會與其他演算法結合。

例:HDU 1496

#include <iostream>  

#include <algorithm>  

#include <cstring>  

using namespace std;  

int val[40010];  

int main() {  

    pair <int*, int*> p;  

    int a, b, c, d;  

    while (cin >> a >> b >> c >> d) {  

        if( (a > 0 && b > 0 && c > 0 && d > 0) || (a < 0 && b < 0 && c < 0 && d < 0)){  

            cout << 0 << endl;  

            continue;  

        }  

        memset(val, 0, sizeof(val));  

        int k = 0;  

        for (int i = -100; i <= 100; i++){  

            if (i == 0) continue;  

            for (int j = -100; j <= 100; j++) {  

                if (j == 0) continue;  

                val[k++] = a*i*i + b*j*j;  

            }  

        }  

        sort(val, val+k);  

        int cnt = 0;  

        for (int j = -100; j <= 100; j++) {  

            if (j == 0) continue;  

            for (int i = -100; i <= 100; i++) {  

                if (i == 0) continue;  

                int sum = c*j*j + d*i*i;  

                p = equal_range(val, val+k, -sum);  

                cnt += p.second - p.first;  

            }  

        }  

        cout << cnt << endl;  

    }  

    return 0;  

}  

 

3、排列系列

next_permutation是一個求一個排序的下一個排列的函式,可以遍歷全排列要包含標頭檔案<algorithm>,與之完全相反的函式還有prev_permutation

int 型別的next_permutation

int main()

{

     int a[3];

     a[0]=1;a[1]=2;a[2]=3;

     do

     {

         cout<<a[0]<<""<<a[1]<<" "<<a[2]<<endl;

     } while (next_permutation(a,a+3));

}

輸出:

 1 2 3

 1 3 2

 2 1 3

 2 3 1

 3 1 2

 3 2 1

char 型別的next_permutation

int main()

{

     char ch[205];

     cin >> ch;

     sort(ch, ch + strlen(ch) );

     char *first = ch;

     char *last = ch + strlen(ch);

     do {

         cout<< ch << endl;

     }while(next_permutation(first, last));

     return 0;

}

string 型別的next_permutation

int main()

{

     string line;

     while(cin>>line&&line!="#")

    {

         if(next_permutation(line.begin(),line.end()))

             cout<<line<<endl;

         else cout<<"Nosuccesor\n";

    }

}

int main()

{

     string line;

     while(cin>>line&&line!="#")

     {

         sort(line.begin(),line.end());

         cout<<line<<endl;

         while(next_permutation(line.begin(),line.end()))

             cout<<line<<endl;

     }

}

 

4、常用函式

copycopy_ifcopy直接拷貝,比for迴圈高效,最壞為線性複雜度,而且這個可以說是一個copy族函式,還有類似的滿足一定條件的copy_if等。

findfind_i查詢第一個匹配的值或第一個滿足函式使其為true的值位置,沒有返回指定區間的末尾,線性複雜度,還有一些不怎麼常用的find族函式就不多介紹了。

countcount_if返回匹配或使函式為true的值的個數,線性複雜度。

search這是尋找序列是否存在於另一個序列中的函式,挺好用的,某些簡單的尋找公共子串的題就可以這樣寫,時間複雜度二次。

reverse翻轉一個區間的值,我經常遇到需要這種題,直接reverse了,不需要for迴圈了,主要是方便。

for_each直接對一個區間內的每個元素執行後面的函式操作,寫起來簡單。

maxminmax_elementmin_element:尋找兩個數或者一個區間的最大最小值,都可以新增比較函式引數。

集合操作函式:includesset_unionset_differenceset_intersectionset_symmetric_difference、前面這些函式的最差複雜度為線性,另外附加一個序列的操作函式merge,相當於歸併排序中的合併函式,時間複雜度為線性,注意這些函式的操作物件都必須是升序的。

例:

#include<cstdio>   

#include<algorithm>   

using namespace std;    

void out(int a) { if (a != -1) printf("%d ",a); }   

int main() {   

    int a[5] = {1, 8, 10, 52, 100};   

    int b[5] = {6, 8, 9, 10, 1000};   

    int c[20];   

    printf("a集合為:");   

    for_each(a, a+5, out);   

    puts("");   

    printf("b集合為:");   

    for_each(b, b+5, out);   

    puts("");   

    //判斷b是否是a的子集。   

    if(includes(a, a+5, b, b+5)) printf("bis a sub set of a\n");   

    //合併兩個有序序列,必須為合併後的序列分配空間,否則程式會崩潰。   

    printf("兩個集合的合併序列為:");   

    merge(a, a+5, b, b+5, c);   

    for_each(c, c+10, out);   

    puts("");   

    //求兩個集合的並集。   

    fill(c, c+20, -1);   

    set_union(a, a+5, b, b+5, c);   

相關推薦

NOIP複賽複習STL演算法結構模板

STL演算法 STL 演算法是一些模板函式,提供了相當多的有用演算法和操作,從簡單如for_each(遍歷)到複雜如stable_sort(穩定排序),標頭檔案是:#include <algorithm>。常用STL 演算法庫包括:sort快速排序演算法、二分

NOIP複賽複習STL容器字串模板

STL容器 STL 容器是一些模板類,提供了多種組織資料的常用方法。常用的STL容器包括pair(組合)、list(列表,類似於連結串列)、vector(向量,類似於陣列)、priority_queue(優先佇列)、set(集合)、map(對映)、stack(棧)等,通過模板的引數

NOIP複賽複習競賽環境注意事項

一、比賽不提供紙質試題,只提供電子版試題檔案。 該檔案壓縮包儲存在計算機桌面上。監考人公佈密碼後,選手自行解密試題。 試題解壓密碼會影響一個人的心情,一定要一次輸對,注意大小寫,不要邊輸入邊檢查,要對自己有自信。 二、江蘇複賽選手上機可自選windows或linux作業系統。

NOIP複賽複習常見問題常用策略

數學類問題 1. 精度處理(高精度、實數處理、各種浮點型別處理方法) 2. 組合數學問題(斐波那契數列、第二類數、卡特蘭數、Polya原理、排列組合計數、加法原理與乘法原理) 3. 進位制問題(特定二進位制串的統計、二分查詢、利用二進位制進行路徑、狀

NOIP複賽複習十三圖論演算法鞏固提高

一、圖的儲存   1、鄰接矩陣   假設有n個節點,建立一個n×n的矩陣,第i號節點能到達第j號節點就將[i][j]標記為1(有權值標記為權值),  樣例如下圖:   /*無向圖,無權值*/ i

NOIP複賽複習演算法分析排序模板

演算法分析 演算法分析的目的是預測演算法所需的資源,如計算時間(CPU 消耗)、記憶體空間(RAM 消耗)、通訊時間(頻寬消耗)等,以及預測演算法的執行時間,即在給定輸入規模時,所執行的基本運算元量,或者稱為演算法複雜度。 演算法的執行時間取決於輸入的資料特徵,輸入

NOIP複賽複習怎樣才能拿到高分?

摘要 考場策略和程式測試是資訊學競賽中非常重要的環節,很多優秀的選手在很多比賽中總是會在這兩個環節上犯下這樣和那樣的錯誤,導致得到的分數和實力不成正比,最後留下了無盡的遺憾。本文將探討一些這兩個環節上值得注意的地方,提出一些可行的方法,分享一些經驗,以此希望幫助選手們在比賽中發揮水平,減少失

NOIP複賽複習如何設計測試資料?

有些同學參加一次資訊學比賽之後,自我感覺非常不錯,但是測評結果成績卻並不理想。造成這種情況的原因有多方面,但是我認為其中不可忽視的一大原因就是在寫完程式之後,他們並不知道如何保證程式的正確性。在這裡,我就這個問題提出一點自己的看法。 先從考試的時間分配問題講起。很多同學覺得考試時間很充分,N

NOIP複賽複習程式對拍圖論模板

程式對拍 所謂“對拍”,顧名思義,就是讓兩者相互比對。所謂“兩者”,一是你要測試的程式,二是一個答案在該程式在一定範圍(時間/空間)內結果必定正確的程式(一般是用暴力求解的程式)。對拍一般需要造資料程式(data.exe),保證正確性的暴力對拍程式(test.exe)與測試程式(以moo.e

NOIP複賽複習讀寫外掛高精度模板

讀入輸出掛 讀入輸出掛就是逐個字元地讀入資料,從而讓讀入更加快速。輸出掛的原理也是一樣的,都是通過將輸出數字變成輸出字元以加快速度。當然輸入輸出外掛一般用在大量輸入輸出的情況下,這樣價效比才高一些,否則得不償失。 void Rd(int &res){  &nbs

NOIP複賽複習檔案讀寫數論模板

檔案讀入讀出 假設題目名為“add”,那麼資料夾名為“add”,c++程式名為“add.cpp”,讀入檔名為“add.in”,輸出檔名為“add.out”。四個的拼寫均不可有誤,包括大小寫差異。千萬不要除錯後就忘記修改檔案讀入讀出了。  #include<cstdio&

包建強的培訓課程5演算法資料結構

演算法與資料結構 一、簡介 本課程是基於資料結構來設計的,蒐羅了各大公司面試過程中經常被問到的300多個演算法題目,從中遴選出70道經典題目,分為單鏈表、陣列、二叉樹、棧、數字、邏輯推理等多個類別。 本課程將培訓學員的邏輯思維能力,學以致用,在實戰中編寫出效能更好、邏輯更嚴謹的程式。 本課程適

NOIP複賽複習十四字串演算法鞏固提高

一、Trie樹   1.定義: 通過字串建成一棵樹,這棵樹的節點個數一定是最少的。例如:4個字串"ab","abc","bd","dda"對應的trie樹如下: 其中紅色節點表示存在一個字串是以這個點結尾的。  一個性質:在樹上,兩個點u,

NOIP複賽複習十二數論演算法鞏固提高

一、數論    1.數   整數、自然數(大於等於0的整數)、正整數(大於0的整數)、負整數、非負整數、非正整數、非零整數、奇數偶數。   2.整除性   設a,b∈Z,如果存在c∈Z並且a=bc,則

NOIP複賽複習十一基礎演算法鞏固提高

一、倍增演算法:   定義:用f[i][j]表示從i位置出發的2j個位置的資訊綜合(狀態) 一個小小的問題:為什麼是2j而不是3j,5j,…?因為,假設為kj,整個演算法的時間複雜度為(k-1)logk,當k=2時,時間複雜度最小。 這個演算法的三個應用:

NOIP複賽複習十五動態規劃鞏固提高

經典例題:數字金字塔(Luogu 1216)  寫一個程式來查詢從最高點到底部任意處結束的路徑,使路徑經過數字的和最大。每一步可以走到左下方的點也可以到達右下方的點。 我們現在這裡討論搜尋如何實現:  狀態:目前在第x行第y列 

人臉識別之人臉對齊--LBF演算法

整體來看,其實 ,ESR是基礎版本的形狀迴歸,ERT將回歸樹修改為GBDT,由原始的直接回歸形狀,改進為迴歸形狀殘差,而LBF,是加速特徵提取,由原來的畫素差分特徵池,改為隨機選擇點。   轉自:http://blog.csdn.net/qq_14845119/article/de

javaScript複習物件、閉包

Function物件 Function物件:一切(引用型別)都是物件,物件是屬性的集合 undefined, number, string, boolean屬於簡單的值型別,不是物件。剩下的一切都是物件,包括函式、陣列、物件、null、new Number(10)都是物件。他們都是引用型別。

Java基礎知識複習-- 遍歷ArrayList的三種方法

第一種遍歷 普通for迴圈 可以用size()和get()分別得到大小,和獲取指定位置的元素,結合for迴圈就可以遍歷出ArrayList的內容 第二種遍歷,使用迭代器 從最開始的位置判斷"下一個"位置是否有資料,如果有就通過next取出來,並且把指標向

資料結構演算法複習10—— 字尾陣列字串問題

放此待查。 RMQ 問題 http://www.notonlysuccess.com/?p=356 利用字尾陣列求解一個字串中最長重複子串問題 http://cylixstar.blogbus.com/logs/28350301.html http://imlazy.ycool.com/post.20118