點此看題面
大致題意:給你乙個長度為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君會...