51nod 1709 複雜度分析

2022-05-08 03:54:12 字數 1350 閱讀 7321

考慮樸素的暴力,相當於列舉u點的每個祖先f,然後統計一下這個點f除了某個兒子裡有u的那個子樹之外的節點個數,乘上f到u距離的二進位制1的個數

那麼我們用倍增來實現這個東西,每次列舉二進位制的最高位j,用dfs序列舉點u,找到u的距離為\(2^j\)的祖先,那麼在fa[u][j]這個祖先的位置,j這一位的出現次數包括了距離u所有距離小於\(2^j\)的點(這個邊列舉最高位邊統計就好),同時還要加上除了j這一位其他距離的二進位制1的個數

例如我們列舉的最高位是\(2^4\)

我們對於乙個距離為11的點,拆分成1011,統計的時候這3的1的個數還要統計一遍,用乙個陣列記錄一下就好

#include #include #include #include #include #include #include #include #define enter putchar('\n')

#define space putchar(' ')

//#define ivorysi

#define pb push_back

#define mo 974711

#define pii pair#define mp make_pair

#define fi first

#define se second

#define maxn 100005

using namespace std;

typedef long long int64;

typedef double db;

templatevoid read(t &res)

while(c >= '0' && c <= '9')

res = res * f;

}templatevoid out(t x)

if(x >= 10) out(x / 10);

putchar('0' + x % 10);

}int n;

struct node e[maxn * 2];

int head[maxn],sume,fa[maxn][20],siz[maxn],last[maxn],l[maxn],idx,cnt[maxn];

int64 ans,bit[maxn];

void add(int u,int v)

void dfs(int u)

}}void init()

dfs(1);

}void solve()

}for(int j = 0 ; j <= 17 ; ++j)

last[u] = fa[last[u]][j];

} }

out(ans);enter;

}int main()

51Nod1709 複雜度分析

題目鏈結 一道很有意思的題。我們考慮按位累計貢獻。記錄 dp i j 為上一步倍增跳了 2 j 步,跳到了 i 點的所有狀態 1 的個數和。可以理解為,對於乙個兒子u和他的祖先v的深度差,可以表示為乙個二進位制數。我們倍增的將u跳到v,每次跳的長度一定比上次小,且一定是 2 k 對於乙個點i,上一步...

樹論 倍增 51nod1709 複雜度分析

倍增與位運算有很多共性 這題做法有一點像 線段樹上二分 和 線段樹套二分 的關係。給出一棵n個點的樹 以1號點為根 定義dep i 為點i到根路徑上點的個數。眾所周知,樹上最近公共祖先問題可以用倍增演算法解決。現在我們需要算出這個演算法精確的複雜度。我們定義計算點i和點j最近公共組先的精確複雜度為b...

複雜度分析 時間複雜度分析和空間複雜度分析

其實,只要講到資料結構與演算法,就一定離不開時間 空間複雜度分析。而且我個人認為,複雜度分析是整個演算法學習的精髓,只要掌握了它,資料結構和演算法的內容基本上就掌握了一半。1.時間複雜度分析 對於剛才羅列的複雜度量級,我們可以粗略地分為兩類,多項式量級和非多項式量級。其中,非多項式量級只有兩個 o ...