考慮樸素的暴力,相當於列舉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 ...