( 其他演算法與技巧 )【 莫隊 】在使用莫隊時總有些題目卡莫隊,這時候就需要用到奇偶優化+快讀來進行提速。推薦閱讀:
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,中間棄了一段,然後今天學弟學莫隊,拿出這個題,他也沒什麼想法,然後我頓時退一步海闊天空了。最開...