分塊 區間眾數(金牌導航 分塊 1)

2021-10-20 07:34:11 字數 2309 閱讀 9725

給出乙個數列,和若干詢問,每個詢問讓你求乙個區間內的眾數

6 3 

1 2 3 2 1 2

1 5

3 6

1 5

1 

2 1

1⩽n

⩽4×1

04,1

⩽m⩽5

×104

,1⩽a

i⩽10

91\leqslant n \leqslant 4\times 10^4,1\leqslant m \leqslant 5\times 10^4,1\leqslant a_i \leqslant 10^9

1⩽n⩽4×

104,

1⩽m⩽

5×10

4,1⩽

ai​⩽

109對於求區間眾數,線段樹不易維護

考慮分塊

先對數列a離散化

然後列舉一遍數列a,求出num

i,

jnum_

numi,j

​(前i個塊中j顏色出現的次數),時間o(n

n)

o(n\sqrt)

o(nn​)

然後求一段連續塊的眾數,先列舉左段的塊,然後暴力搜右節點,時間o(n

n)

o(n\sqrt)

o(nn​)

然後對於每次查詢,暴力列舉不在整乙個塊的數

#include

#include

#include

#include

#include

#define ll long long

#define n 40010

#define qn 210

using

namespace std;

int n, m, x, y, g, l, r, nn, nm, a[n]

, b[n]

, p[n]

, f[qn]

[qn]

, num[qn]

[n];

intmain()

sort

(b +

1, b +

1+ n)

; g =

unique

(b +

1, b +

1+ n)

- b -1;

for(

int i =

1; i <= n;

++i)

a[i]

=lower_bound

(b +

1, b +

1+ g, a[i]

)- b;

nn =

sqrt

(n);

g =0;

nm = n / nn +

(n % nn?1:

0);for

(int i =

1; i <= n;

++i)}if

(g < nm)

for(

int i =

1; i <= nm;

++i)

}memset

(p,0

,sizeof

(p))

; g =0;

while

(m--

)for

(int i = x; i <= y;

++i)

p[a[i]]--

;printf

("%d\n"

, b[g]);

continue;}

g = f[l]

[r];

for(

int i = x; i <=

min(

(l -1)

* nn, n)

;++i)

for(

int i =

max(r * nn +1,

1); i <= y;

++i)

for(

int i = x; i <=

min(

(l -1)

* nn, n)

;++i)

//把原來的清掉,不然要o(n),會超時

p[a[i]]--

;for

(int i =

max(r * nn +1,

1); i <= y;

++i)

p[a[i]]--

;printf

("%d\n"

, b[g]);

}return0;

}

分塊 (查詢區間最小眾數

題目鏈結 1 include2 include3 include4 include5 include6 include 7 include8 include9 include10 include11 include12 include13 include14 include 15 include16...

數列分塊入門9 區間眾數

原題 題解 基本題意求 l,r 的最小眾數,對於集合 a,b 顯然 mode a and b 屬於 mode a and b。這樣就可以分塊,預處理f i j 表示i j的眾數。每次查詢時暴力查詢頭尾兩塊的數和中間塊的眾數就可以,關於查詢x在 l,r 出現了幾次,用動態陣列存放x的下標,二分查詢就好...

BZOJ2724 蒲公英 題解(分塊 區間眾數)

題目鏈結 題目大意 給定一段長度為 n 的序列和 m 次詢問,每次詢問區間 l,r 內的最小的眾數。n leq 40000,a i leq 10 9 因為 a i leq 10 9 顯然不能開那麼大的陣列。所以要離散化。對於離散化後的陣列,我們維護兩個值 sum i j 和 p i j sum i ...