洛谷3396 雜湊衝突(大力分塊)

2021-08-27 20:42:45 字數 3707 閱讀 7352

點此看題面

大致題意:給你乙個長度為n

nn的陣列val

valva

l以及m

mm個操作,操作有兩種:一種是將val

xval_x

valx

​修改為y

yy,另一種操作是求出∑va

li(i

%x=y

)\sum val_i(i\%x=y)

∑vali​

(i%x

=y)。

樸素的暴力

我們先來寫乙個樸素的暴力,**如下:

#include

#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)<0?-(x):(x))

#define ll long long

#define ull unsigned long long

#define swap(x,y) (x^=y,y^=x,x^=y)

#define fsize 100000

#define tc() (finnow==finend&&(finend=(finnow=fin)+fread(fin,1,fsize,stdin),finnow==finend)?eof:*finnow++)

#define pc(ch) (foutsize#define n 150000

int foutsize=

0,outputtop=0;

char fin[fsize]

,*finnow=fin,

*finend=fin,fout[fsize]

,outputstack[fsize]

;using

namespace std;

int n,q,a[n+5]

;inline

void

read

(int

&x)inline

void

read_alpha

(char

&x)inline

void

write

(int x)

intmain()

}return

fwrite

(fout,

1,foutsize,

stdout),

0;}

我們可以驚喜地發現,這樣就有91

9191

分了。如果你寫得足夠優秀,說不定可以直接ac。

預處理答案+暴力更新

我們可以用ans

i,

jans_

ansi,j

​來記錄詢問i,j

i,ji,

j時的答案。

首先,o(n

2)

o(n^2)

o(n2

)預處理出答案,並用o(n

2)

o(n^2)

o(n2

)大小的陣列把答案存下來,對於詢問,可以o(1

)o(1)

o(1)

輸出答案,並o(n

)o(n)

o(n)

暴力更新。

然後,我們悲劇地發現n

≤150000

n≤150000

n≤1500

00,還沒等到tle

tletl

e,直接記憶體炸飛了。。。

**略。

如何優化

我們可以對第二個上天了的**進行優化。

記錄全部答案畢竟所耗記憶體太大了,能不能只記錄一部分的答案,然後另一部分暴力算呢?

就可以考慮分塊

我們可以先o(n

n)

o(n\sqrt n)

o(nn​)

暴力預處理模數≤

n≤\sqrt n

≤n​時的答案,並用ans

ansan

s陣列將其儲存下來。

然後,對於修改,我們可以在o(n

)o(\sqrt n)

o(n​

)的時間複雜度內列舉每乙個小於等於n

\sqrt n

n​的模數,然後更新對應的ans

ansan

s。對於詢問,我們分兩種情況討論:

這樣的演算法應該是o((

n+m)

n)

o((n+m)\sqrt n)

o((n+m

)n​)

的。乙個玄學的小優化

雖然我個人認為最優塊的大小應該是o(n

)o(\sqrt n)

o(n​

),但是,實踐證明,以o(n

3)

o(\sqrt[3] n)

o(3n​)

為塊的大小要比o(n

)o(\sqrt n)

o(n​

)快很多。

**

#include

#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)<0?-(x):(x))

#define ll long long

#define ull unsigned long long

#define swap(x,y) (x^=y,y^=x,x^=y)

#define fsize 100000

#define tc() (finnow==finend&&(finend=(finnow=fin)+fread(fin,1,fsize,stdin),finnow==finend)?eof:*finnow++)

#define pc(ch) (foutsize#define n 150000

#define size 400

int foutsize=

0,outputtop=0;

char fin[fsize]

,*finnow=fin,

*finend=fin,fout[fsize]

,outputstack[fsize]

;using

namespace std;

int n,q,blo,a[n+5]

,ans[size]

[size]

;inline

void

read

(int

&x)inline

void

read_alpha

(char

&x)inline

void

write

(int x)

intmain()

else

//對於詢問操作

//如果模數≤n^(1/3),直接輸出預處理得到的答案

for(i=y,res=

0;i<=n;i+

=x) res+

=a[i]

;//否則,暴力統計答案

write

(res),pc

('\n');

//輸出答案}}

return

fwrite

(fout,

1,foutsize,

stdout),

0;}

洛谷3396 雜湊衝突 分塊

眾所周知,模數的hash會產生衝突。例如,如果模的數p 7,那麼4和11便衝突了。b君對hash衝突很感興趣。他會給出乙個正整數序列value。自然,b君會把這些資料存進hash池。第value k 會被存進 k p 這個池。這樣就能造成很多衝突。b君會給定許多個p和x,詢問在模p時,x這個池內數的...

洛谷 P3396 雜湊衝突 分塊

題目鏈結 給你個數列,編號為1 n 1 n 給出兩種操作 我們先從最為暴力的思路出發 我們可以把要求的東西簡寫成su m x y sum x y 代表的含義是模 x x 餘y role presentation style position relative y y的編號對應的數字之和,下面我們需要...

洛谷P3396 雜湊衝突 分塊

時空限制 1000ms 128mb 題目描述 眾所周知,模數的hash會產生衝突。例如,如果模的數p 7,那麼4和11便衝突了。b君對hash衝突很感興趣。他會給出乙個正整數序列value。自然,b君會把這些資料存進hash池。第value k 會被存進 k p 這個池。這樣就能造成很多衝突。b君會...