P2709 小B的詢問 莫隊演算法

2022-01-12 15:12:22 字數 1689 閱讀 5790

莫隊演算法被稱為優雅的暴力,是一種 毒瘤暴力的 區間操作演算法。初學莫隊,記錄一下思想。

對於多個區間查詢[l,r]這類問題,可以離線操作,常規做法還有對左區間或者右區間從小到大排序,讓左指標或者右指標只走一遍,有效降低時間複雜度。但是遇到[1,1000000],[2,3],[3,1000000],[4,5],[5,1000000]這樣的查詢區間,雖然可以保證左區間只掃一遍,但是右指標需要從頭到尾來回掃,時間複雜度一下子就上去了。莫隊演算法就是專門針對這種毒瘤題目的。

它的主要思想是分塊,對區間的範圍n開根號得到乙個d,每乙個查詢區間[l,r]的左區間l除以d,區間看作是全域性的第x塊,不同塊按的區間塊從小到大排序,同一塊的按右區間從小到大排序(不同塊看左,同塊看右)。

分塊排序寫乙個自定義比較函式就可以了。時間複雜度n*sqrt(n),具體證明看其他大佬部落格吧。

對於查詢的區間[l,r],指標移動操作比較常規,無非是左指標和右指標左右移動,[5,7]的答案可以由[5,8]或者[5,6]移動一次右指標解決,也可以由[4,7]或[6,7]移動一次左指標解決。對於區間查詢的貢獻,減去原來的,加上現在的。

入門題p2709

題意看了很久才懂,解釋一下資料,1到4出現了2個1,對答案貢獻2*2,出現1個2,對答案貢獻1*1,出現1個3,對答案貢獻1*1,加起來就是6。

#include#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

#define inf 0x3f3f3f3f //

/填充無限小-0x7f

using

namespace

std;

struct

node

;node b[

50005

];int a[50005

];int num[50005

];int

n,m,k;

intd;

bool cmp1(node p1,node p2)///

分塊,對左區間開根號,左邊不在同一塊按左區間小到大排序,左邊在同一塊按右邊大小排序

bool cmp2(node p1,node p2)///

離線操作後恢復答案次序

int main()///

p2709 莫隊入門

sort(b+1,b+m+1

,cmp1);

int l=1,r=1

; num[ a[

1] ]=1

; ll ans=1

;

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

while(l///

左指標往右

while(r///

右指標往右

while(r>b[i].r)///

右指標往左

b[i].ans=ans;

}sort(b+1,b+m+1

,cmp2);

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

printf(

"%lld\n

",b[i].ans);

return0;

}

P2709 小B的詢問 莫隊演算法

題意 小b有乙個序列,包含n個1 k之間的整數。他一共有m個詢問,每個詢問給定乙個區間 l.r 求sigma c i 2 的值,其中i的值從1到k,其中c i 表示數字i在 l.r 中的重複次數。小b請你幫助他回答詢問。就是求區間不同數字個數的平方和 注意平方數可以拆開從1 n 遞推。include...

P2709 小B的詢問(莫隊演算法)

小b 有乙個長為 nn 的整數序列 aa,值域為 1,k 1,k 他一共有 mm 個詢問,每個詢問給定乙個區間 l,r l,r 求 sum limits k c i 2i 1 k ci2 其中 c ici 表示數字 ii 在 l,r l,r 中的出現次數。小b請你幫助他回答詢問。第一行三個整數 n,...

P2709 小B的詢問 莫隊

題目描述 小b有乙個序列,包含n個1 k之間的整數。他一共有m個詢問,每個詢問給定乙個區間 l.r 求sigma c i 2 的值,其中i的值從1到k,其中c i 表示數字i在 l.r 中的重複次數。小b請你幫助他回答詢問。輸入輸出格式 輸入格式 第一行,三個整數n m k。第二行,n個整數,表示小...