[补档计划] 树2 - 树上倍增
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[补档计划] 树2 - 树上倍增相关的知识,希望对你有一定的参考价值。
[SCOI2016] 萌萌哒
题意
求有多少个无前导零的 $N(N\le 10^5)$ 位数 $A$ , 满足 $M(M\le 10^5)$ 个限制条件 $L~R~X~Y$ : $A[L+i] = A[X+i]$ .
分析
区间的信息就先对 ST 表用并查集, 然后下传.
实现
#include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #include <cmath> #define F(i, a, b) for (register int i = (a); i <= (b); i++) #define D(i, a, b) for (register int i = (a); i >= (b); i--) const int L = (int)1e9+7; int n, m; int f[2000000], c; int cnt, res; inline int rd(void) { int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; int x = 0; for (; isdigit(c); c = getchar()) x = x * 10 + c - ‘0‘; return x * f; } inline int id(int i, int j) { return i * n + j; } inline int Find(int x) { return f[x] == x ? x : f[x] = Find(f[x]); } inline void Union(int x, int y) { f[Find(x)] = Find(y); } int main(void) { #ifndef ONLINE_JUDGE freopen("xsy2412.in", "r", stdin); freopen("xsy2412.out", "w", stdout); #endif n = rd(), m = rd(), c = (int)log2(n); for (int i = 1, up = id(c, n); i <= up; i++) f[i] = i; F(i, 1, m) { int l = rd(), r = rd(), x = rd(), y = rd(); for (int j = c; j >= 0 && r >= l; j--) if (r - (1<<j) + 1 >= l) { Union(id(j, r), id(j, y)); r -= (1<<j), y -= (1<<j); } } D(i, c, 1) F(j, 1<<i, n) { int k = f[id(i, j)] - i*n; if (j != k) { Union(id(i-1, j), id(i-1, k)); Union(id(i-1, j - (1<<(i-1))), id(i-1, k - (1<<(i-1)))); } } F(i, 1, n) cnt += (i == Find(i)); res = 9; F(i, 2, cnt) res = 1LL * res * 10 % L; printf("%d\n", res); return 0; }
以上是关于[补档计划] 树2 - 树上倍增的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 3551[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树
洛谷 P2680 [NOIP2015 提高组] 运输计划(二分,树上查分,树上倍增,LCA)