本題是一道講解根號分治思想的論文題(然鵝我並無找到論文),正ios
如論文中所說,根號算法——不只是分塊,根號分治利用的思想和分塊像c++
似卻又不一樣,某一篇洛穀日報中說過,分塊算法實質上是一種是經過分紅算法
多塊後在每塊上打標記以實現快速區間修改,區間查詢的一種算法。根號優化
分治與其思路類似,將本來若一次性解決時間複雜度很高的問題分塊去解spa
決來下降總體的時間複雜度。code
以本題舉例子哈希衝突ci
本題做爲論文的第一道題目,是一道很好的練習題,注意,本體給出的get
\(value[i]\) 是 \(i\) 在序列中出現的次數,不要把題讀錯了(一開始我就讀錯了)string
咱們首先閱讀題目,發現,不管是 \(O(n^2)\) 預處理, \(O(1)\) 查詢,仍是在io
查詢時直接\(O(n^2)\)獲取答案,都是 \(O(n^2)\) 的時間複雜度,咱們考慮對
其進行優化,咱們能夠考慮將\(p\),也就是模數按根號分塊處理
對於 \(p<=\sqrt{q}\) 咱們直接 \(O(n\sqrt{n})\) 進行預處理,
for(int i=1;i<=n;i++){ v=read(); val[i]=v; } size=sqrt(n); for(int i=1;i<=n;i++){ for(int p=1;p<=size;p++){ ans[p][i%p]+=val[i]; } }
\(ans[p][i]\) 表示在 \(%p\) 後值爲 \(i\)的數的個數
對 \(p>\sqrt{q}\) 的狀況,
咱們直接暴力得出答案,暴力獲得答案的時間複雜度爲 \(O(\sqrt{n})\)
int an=val[y]; for(int i=x+y;i<=n;i+=x){ an+=val[i]; } cout<<an<<endl;
\(an=val[y]\) 是爲了處理 \(y%x=y\) \((y<x)\) 的狀況,爲何說咱們暴力跳
答案時間複雜度是 \(O(\sqrt{n})\) 呢?咱們當前的 \(p>\sqrt{n})\) 由於統
計答案時每一次要跳\(p\)個數,因此有貢獻的數必定小於 \(\frac{n} {p}\) 也就是 \(\sqrt{n}\) ,因此暴力獲得答案的時間複雜度爲 \(O(\sqrt{n})\)
每一次修改,咱們只須要修改 \(p<=\sqrt{n}\) 的狀況便可,時間複雜度也是 \(O(\sqrt{n})\)
cin>>x>>y; int l=y-val[x]; val[x]=y; for(int p=1;p<=size;p++){ ans[p][x%p]+=l; }
因此在本題,咱們運用根號分治的想法,把時間複雜度由本來的\(O(n^2)\)
優化到了 \(O(n\sqrt{n})\) 從而解決本題。
莫名以爲根號分治挺像折半搜索
,推薦一道練習題CF444D DZY Loves Strings
仍是頗有難度的
放一下所有代碼吧
#include<iostream> #include<string> #include<string> #include<cstdio> #include<cmath> #define int long long using namespace std; const int maxn=3e5+10; inline int read(){ int ret=0; int f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-f; ch=getchar(); } while(ch<='9'&&ch>='0'){ ret=ret*10+(ch^'0'); ch=getchar(); } return ret*f; } int val[maxn]; int n,m; int p; int ans[2000][2000]; int size; char a; signed main(){ // freopen("a.in","r",stdin); n=read(); m=read(); int v; for(int i=1;i<=n;i++){ v=read(); val[i]=v;//???????? } size=sqrt(n);//???? for(int i=1;i<=n;i++){ for(int p=1;p<=size;p++){ ans[p][i%p]+=val[i]; } } int x,y; while(m--){ cin>>a; if(a=='A'){ x=read(); y=read(); if(x<=size){ cout<<ans[x][y]<<endl; } else{ int an=val[y]; for(int i=x+y;i<=n;i+=x){ an+=val[i]; } cout<<an<<endl; } } if(a=='C'){ cin>>x>>y; int l=y-val[x]; val[x]=y; for(int p=1;p<=size;p++){ ans[p][x%p]+=l; } } } return 0; }
到這裏本題解就結束了
完結撒花!!