[ SCOI 2016 ] 萌萌哒
题目
思路
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010, mod = 1e9 + 7;
int n, m, f[N][20];
// k 是倍增自带的, 忽略 k 就和普通并查集一模一样了
int find(int x, int k) { return f[x][k] != x ? (f[x][k] = find(f[x][k], k)) : f[x][k]; }
void merge(int x, int y, int k) { f[find(x, k)][k] = f[find(y, k)][k]; }
int main() {
cin >> n >> m;
for (int j = 0; j <= 19; j++)
for (int i = 1; i <= n; i++)
f[i][j] = i;
for (int a, b, c, d; m-- && cin >> a >> b >> c >> d; )
for (int i = 19; i >= 0; i--)
if (a + (1 << i) - 1 > b) continue; // 比右边区间大的就跳过
else merge(a, c, i), a += 1 << i, c += 1 << i; // 倍增跳
for (int j = 20; j >= 1; j--) // 注意 >= 1
for (int i = 1; i + (1 << j) - 1 <= n; i++)
merge(i, find(i, j), j - 1), // 推到两个子区间
merge(i + (1 << (j - 1)), find(i, j) + (1 << (j - 1)), j - 1);
int cnt = 0, res = 9;
for (int i = 1; i <= n; i++) cnt += (f[i][0] == i); // 判断几个集合
for (int i = 1; i <= cnt - 1; i++) res = 1ll * res * 10 % mod; // 暴力算就行
cout << res << endl;
return 0;
}