( 其他演算法與技巧 ) 莫隊

2021-10-02 10:47:58 字數 2913 閱讀 6017

( 其他演算法與技巧 )【 莫隊 】

推薦閱讀:

在使用莫隊時總有些題目卡莫隊,這時候就需要用到奇偶優化+快讀來進行提速。

struct node q[200005];

int rule( node a, node b )

q[i].l = read() ;

q[i].r = read() ;

q[i].bl=((q[i].l-1)/sqrt(n)/2)+1;

首先明確:莫隊適用於不帶修改的多次區間查詢眾所周知,莫隊是由莫濤大神提出的,一種玄學毒瘤暴力騙分區間操作演算法,它以簡短的框架、簡單易記的板子和優秀的複雜度聞名於世。然而由於莫隊演算法應用的毒瘤,很多可做的莫隊模板題都有著較高的難度評級,令很多初學者望而卻步。然而,如果你真正理解了莫隊的演算法原理,那麼它用起來還是很簡單的。當然某些套左套右的毒瘤除外。

luogu p1972 [sdoi2009]hh的項鍊

題目描述

hh 有一串由各種漂亮的貝殼組成的項鍊。hh 相信不同的貝殼會帶來好運,所以每次散步完後,他都會隨意取出一段貝殼,思考它們所表達的含義。hh 不斷地收集新的貝殼,因此,他的項鍊變得越來越長。有一天,他突然提出了乙個問題:某一段貝殼中,包含了多少種不同的貝殼?這個問題很難回答……因為項鍊實在是太長了。於是,他只好求助睿智的你,來解決這個問題。

輸入格式:

第一行:乙個整數n,表示項鍊的長度。

第二行:n 個整數,表示依次表示項鍊中貝殼的編號(編號為0 到1000000 之間的整數)。

第三行:乙個整數m,表示hh 詢問的個數。

接下來m 行:每行兩個整數,l 和r(1 ≤ l ≤ r ≤ n),表示詢問的區間。

輸出格式:

m 行,每行乙個整數,依次表示詢問對應的答案。

輸入輸出樣例

輸入樣例#1:

6

1 2 3 4 3 5

31 2

3 52 6

輸出樣例#1:

2

24

這個例題卡了莫隊,所以請交資料弱化版:sp3267 dquery - d-query

思路1:

暴力,這題最樸素的作法無非就是從 l 到 r 掃一遍,用陣列記下出現的數,然後求值。

但是這種作法的複雜度是o(n*n)的,肯定過不了;

那麼就需要一些優化:

我們用兩個指標不斷的移動到相應的區間;

int l = 0, r = 1;
然後在移動的時候,我們就不停的add,del,如果當前指標處不在查詢區間內,那麼del操作當前指標,然後向區間內移動乙個位置;如果當前指標在區間內但不在區間邊界,那麼add操作當前指標,向區間邊界移動乙個位置 ;

void add( int x ) // 加入操作

void del( int x ) // 刪除操作

}void work ()

while ( rqr )

printf("%d\n", now);//輸出統計結果}}

就是上面這樣,

這就是莫隊?

不,還有乙個地方,

我們來假設要查詢的區間都不相交呢?

此時ll、r指標在整個序列中移來移去,從頭到尾,又從尾到頭。我們發現左右指標最壞情況下均移動了o(nm)次

那不一樣還是沒有優化。

所以莫隊還要乙個很重要的地方,就是排序;

該如何排序?

這個時候,分塊**萬歲;

把長度為n的序列,分成sqrt(n)個塊;

把查詢區間按照左端點所在塊的序號排個序,如果左端點所在塊相同,再按右端點排序。

排完序後,離線更新答案,指標的移動次數就會降乙個根號n的級別。

講完了。

例題1 : 3sp3267 dquery - d-query

題意: 給出乙個長度為n 的數列,

輸入輸出樣例

輸入 #1

5

1 1 2 1 3

31 5

2 43 5

輸出 #1

3

23

高階版**:

#include using namespace std;

const int maxn = 1e6 + 10;

int n,m;

int a[maxn],via[maxn],ans[maxn];

int l,r,now,block;

struct node q[maxn];

int rule( node a, node b )

cin >> m;

for ( int i=1; i<=m; i++ )

block = sqrt(m/3); // 這樣直接除以block,就不用belong陣列了。

sort(q+1,q+1+m,rule); // 重點!! 這樣排序後就能跑的很快

l = 1; r = 0;

for ( int i=1; i<=m; i++ )

while ( rq[i].r )

ans[q[i].id] = now;

}for ( int i=1; i<=m; i++ )

return 0;

}

例題2:hdu - 6534( 莫隊+權值樹狀陣列 )

莫隊演算法基礎與練習

gym卡了莫隊,於是趁這個機會學一下莫隊 莫隊的核心是分塊排序,這種特殊的排序方法將任務按排序後的順序完成,可以在解決絕大多數無修改的離線區間問題中極大的優化時間 優化了sqrt n 左右 nbut 1457 題意 n個數,尋問10000次,任意區間內的相等數的次數的立方和。題解 將n個數離散化後,...

樹上莫隊演算法

繼續回來寫部落格 記錄點有意思的題目什麼的。貌似寫過這個的沒多少人 所以我也記錄一點。首先序列上的莫隊大家都應該很熟悉了 那麼樹上的莫隊要怎麼搞呢?先來看個題目 spoj cot2 求樹上兩點間路徑上有多少個不同的點權。序列上的莫隊是把詢問按照左端點分塊了 可是樹上沒有左端點,怎麼辦呢?我們把樹分塊...

模板 莫隊演算法

題意 給定乙個大小為n的陣列,陣列中所有元素的大小 n。你需要回答m個查詢。每個查詢的形式是l,r,k。你需要回答在範圍 l,r 中至少重複k次的數字的個數。n,m 100000 誒,這題卡了好久,tle,中間棄了一段,然後今天學弟學莫隊,拿出這個題,他也沒什麼想法,然後我頓時退一步海闊天空了。最開...