歸納(二) 倍增

2022-05-29 04:48:09 字數 2675 閱讀 4371

把一步一步往上爬變成一次一次向前跳,從\(o(n)->o(log_)\)的蛻變,可以解決很多問題。

\[anc[i][k]=anc[anc[i][k-1]][k-1]

\]就這麼一行。

我的\(2^\)級祖先就是我\(2^\)級祖先的\(2^\)級祖先。

就憑這句話,就可以解決很多問題了。

洛谷p1613跑路

小a的工作不僅繁瑣,更有苛刻的規定,要求小a每天早上在6:00之前到達公司,否則這個月工資清零。可是小a偏偏又有賴床的壞毛病。於是為了保住自己的工資,小a買了乙個十分牛b的空間跑路器,每秒鐘可以跑2^k千公尺(k是任意自然數)。當然,這個機器是用longint存的,所以總跑路長度不能超過maxlongint千公尺。小a的家到公司的路可以看做乙個有向圖,小a家為點1,公司為點n,每條邊長度均為一千公尺。小a想每天能醒地盡量晚,所以讓你幫他算算,他最少需要幾秒才能到公司。資料保證1到n至少有一條路徑。

maxlongint是\(2147483647\)。

由於\(n\)只有50,於是就愉悅地用矩陣。

\(t[i][j][k]\) 表示\(i,j\)之間有沒有長度為\(2^\)的邊。

\(dis[i][j]\) 表示\(i,j\)之間的距離。

先處理可以用加速器的情況,在跑floyd。

#includeconst int maxn=50+3;

bool t[maxn][maxn][35];

int dis[maxn][maxn];

int main()

for(int k=1;k<=31;k++)

for(int g=1;g<=n;g++)

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

for(int j=1;j<=n;j++)

if(t[i][g][k-1] && t[g][j][k-1])

for(int k=1;k<=n;k++)

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

for(int j=1;j<=n;j++)

dis[i][j]=std::min(dis[i][j],dis[i][k]+dis[k][j]);

printf("%d\n",dis[1][n]);

}

直接明示。

洛谷p3379【模板】最近公共祖先(lca)

倍增求lca算是最簡單的應用了吧。

原理就是那一行**。

向上跳的方法有多種,可以二進位制拆位,也可以算\(log_\)

#include#include#include#includeconst int maxn=5e5+5;

struct edge e[maxn<<1];

int h[maxn],tot;

void add_edge(int u,int v)

// 2^19 > maxn

int n,m,root;

int anc[maxn][20],lg[maxn],dep[maxn];

void dfs(int nd,int p)

int main() \)級祖先間的路徑最小限重是多少。

於是就解決了。

#include#include#include#include#includeconst int maxn=1e4+5;

const int maxm=5e4+5;

const int oo=0x3f3f3f3f;

int read()

//graph

struct edge e[maxn<<1];

int h[maxn],tot,whi[maxn];

void add_edge(int u,int v,int f)

//build max tree

struct edg e[maxm];

int fa[maxn];

int find(int x)

bool cmp(const edg &a,const edg &b)

//lca

int anc[maxn][23],dep[maxn];

int val[maxn][23];

bool vis[maxn];

void dfs(int nd)

return ;

}int n,m;

int lg[maxn];

int lca(int x,int y)

if(x==y) return ans;

for(int k=lg[dep[x]];~k;k--) if(anc[x][k]!=anc[y][k])

return std::min(ans,std::min(val[x][0],val[y][0]));

}int main()

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

if(!vis[i])

for(int k=1;k<=20;k++)

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

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

lg[i]=lg[i-1]+(1《如果不是看演算法標籤,或許我完全想不到倍增這種做法,但不管怎樣,還是總結一下。

常見題型:

lca

帶\(2^\)的計算

......

其實最重要的是多做題是吧。

對著那個式子一直想一直想。

或許吧。。。

LCA 二分 倍增

兩個最近的點u和v的最近的公共的祖先稱為最近公共祖先 lca 普通的lca演算法,每算一次lca的時間複雜度為線性o n 這裡講lca 二分的方法。首先對於任意的節點v,利用其父節點的資訊,可以通過par2 v par par v 得到向上走兩步的節點。依此資訊可以通過par4 v par2 par...

模板 二分 倍增及其應用

給定陣列 和 數字t,求最大位置k 滿足 sum 1 k t 最簡單的想法就是 字首和 二分,每次查詢時間複雜度log n 對於數列最左端的資料沒有必要 這裡的倍增可以理解為二分的改良優化版,設k點為0,p點為1 1.每次試從當前點k往後加p個數是否小於t 以log速度快速使k逼近答案點 2.隨後再...

《ACM程式設計》 Problem M 二倍問題

題意 描述作為算術能力計畫的一部分,您的學生將獲得2至15個唯一正整數的隨機生成列表,並要求確定每個列表中有多少專案是同一列表中的其他專案的兩倍。你需要乙個程式來幫助你評分。這個程式應該能夠掃瞄列表並輸出每個列表的正確答案。例如,給出列表 1 4 3 2 9 7 18 22 你的程式應該回答3,因為...