莫隊演算法的模板實現

2022-08-18 23:45:18 字數 2507 閱讀 9315

今天的模擬賽t3是一道裸莫隊..本來想了想之前被裸點分治虐的體無完膚決定打暴力的orz(果然我太弱啦!

然後聽說莫隊挺簡單的,看看時間...嗯還有不少 那就學學莫隊吧

莫隊的思想理解起來還是不難的

比如這篇部落格就寫的很好

對於l,r的詢問。設其中顏色為x,y,z....的襪子的個數為a,b,c。。。

那麼答案即為(a*(a-1)/2+b*(b-1)/2+c*(c-1)/2....)/((r-l+1)*(r-l)/2)

化簡得:(a^2+b^2+c^2+...x^2-(a+b+c+d+.....))/((r-l+1)*(r-l))

即:(a^2+b^2+c^2+...x^2-(r-l+1))/((r-l+1)*(r-l))

所以這道題目的關鍵是求乙個區間內每種顏色數目的平方和。

但問題時怎麼快速求解呢?

於是乎學習了下。寫寫學習的心得吧。

對於莫隊演算法我感覺就是暴力。只是預先知道了所有的詢問。可以合理的組織計算每個詢問的順序以此來降低複雜度。要知道我們算完[l,r]的答案後現在要算[l',r']的答案。由於可以在o(1)的時間下得到[l,r-1]和[l,r+1]和[l-1,r]和[l+1,r]的答案.所以計算[l',r']的答案花的時間為|l-l'|+|r-r'|。如果把詢問[l,r]看做平面上的點a(l,r).詢問[l',r']看做點b(l',r')的話。那麼時間開銷就為兩點的曼哈頓距離。所以對於每個詢問看做乙個點。我們要按一定順序計算每個值。那開銷就為曼哈頓距離的和。要計算到每個點。那麼路徑至少是一棵樹。所以問題就變成了求二維平面的最小曼哈頓距離生成樹。

關於二維平面最小曼哈頓距離生成樹。感興趣的可以參考點選開啟鏈結

這樣只要順著樹邊計算一次就ok了。可以證明時間複雜度為n*sqrt(n)這個我不會證明。

但是這種方法程式設計複雜度稍微高了一點。所以有乙個比較優雅的替代品。那就是先對序列分塊。然後對於所有詢問按照l所在塊的大小排序。如果一樣再按照r排序。然後按照排序後的順序計算。為什麼這樣計算就可以降低複雜度呢。

一、i與i+1在同一塊內,r單調遞增,所以r是o(n)的。由於有n^0.5塊,所以這一部分時間複雜度是n^1.5。

二、i與i+1跨越一塊,r最多變化n,由於有n^0.5塊,所以這一部分時間複雜度是n^1.5

三、i與i+1在同一塊內時變化不超過n^0.5,跨越一塊也不會超過2*n^0.5,不妨看作是n^0.5。由於有n個數,所以時間複雜度是n^1.5

於是就變成了o(n^1.5)了。

正如上面所說 複雜度是o(n^1.5)

理解定義..好像不難的樣子?那我們就直接進入打模板環節x

當然,人話題意就是詢問在乙個數列中詢問出現次數等於他本身大小的數有幾個

然後 對於每乙個區間[l,r],很顯然我們用o(1)就可以知道[l+1,r]或[l,r+1]的答案,符合第二個要求

然後再看資料範圍.. 哇 1000000 那正解顯然不是莫隊,但是我們可以用莫隊得到70分

**如下

#pragma gcc optimize("o2")

#include#include#include#include#include#include#include#include#include#include#include#define n 2000001

typedef long long ll;

const int inf=0x3fffffff;

const int maxn=2017;

using namespace std;

inline int read()

while(ch<='9'&&ch>='0')

return f*x;

}struct tsdla[n];

ll cnt[n],b[n],res[n];

int m,n;

bool cmp(tsdl a,tsdl b)

while(ra[i].r)

res[a[i].id]=now; }}

int main()

solve();

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

printf("%lld\n",res[i]);

}

注意不要在莫隊的solve裡加一些奇怪的操作,(就像我在考試裡沒有處理now,是對於每一次詢問暴力對所有點掃是否符合......於是就退化成了o(n1.5m)的垃圾複雜度....樸素暴力才o(nm)...我太弱啦!

模板 莫隊演算法

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

模板 莫隊演算法

這個演算法是由之前的國家隊隊長莫濤巨神 orz 發明的,所以尊稱莫隊演算法。如果我們知道區間 l,r 就能在o 1 求出 l 1,r l 1,r l,r 1 l,r 1 的話,那就可以用莫隊演算法了。1 排序,以左段點所在的塊為第一關鍵字,以右端點為第二關鍵字 2 從左往右處理詢問 離線 3 不斷調...

莫隊演算法模板

一道簡單的莫隊演算法題 莫隊的一般寫法 codeforces 86d include define pb push back define mp make pair using namespace std const int maxn 2e5 7 typedef long long ll struc...