BZOJ4569 [SCOI2016]萌萌哒 【并查集 + 倍增】
2018-05-24 08:02
330 查看
题目链接
题解
倍增的思想很棒
题目实际上就是每次让我们合并两个区间对应位置的数,最后的答案\(ans = 9 \times 10^{tot - 1}\),\(tot\)是联通块数,因为要去前导\(0\),首位不为\(0\)即可
如何快速合并两个区间?
倍增!
每次合并两个区间,我们就利用倍增分成\(logn\)个区间,先用并查集维护其联通性
合并完之后,由大区间推向小区间,将每个倍增的大区间分成两半,分别和其联通块的代表区间的两半合并
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<map> #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt) #define REP(i,n) for (int i = 1; i <= (n); i++) #define mp(a,b) make_pair<int,int>(a,b) #define cls(s) memset(s,0,sizeof(s)) #define cp pair<int,int> #define LL long long int using namespace std; const int maxn = 100005,maxm = 100005,INF = 1000000000,P = 1000000007; inline int read(){ int out = 0,flag = 1; char c = getchar(); while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();} while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();} return out * flag; } int n,m,cnt,pre[maxn * 20],sta[maxn * 20],f[maxn][20],bin[30]; int qpow(int a,int b){ int ans = 1; for (; b; b >>= 1,a = 1ll * a * a % P) if (b & 1) ans = 1ll * ans * a % P; return ans; } inline int find(int u){return u == pre[u] ? u : pre[u] = find(pre[u]);} inline void merge(int a,int b){ int fa = find(a),fb = find(b); pre[max(fa,fb)] = min(fa,fb); } int main(){ bin[0] = 1; for (int i = 1; i <= 25; i++) bin[i] = bin[i - 1] << 1; n = read(); m = read(); for (int j = 0; j <= 17; j++) for (int i = 1; i <= n; i++){ if (i + bin[j] - 1 > n) break; f[i][j] = ++cnt; sta[cnt] = i; pre[cnt] = cnt; } int l,r,ll,rr,len; while (m--){ l = read(); r = read(); ll = read(); rr = read(); len = r - l + 1; for (int i = 17; i >= 0; i--) if (l + bin[i] - 1 <= r){ merge(f[l][i],f[ll][i]); l += bin[i]; ll += bin[i]; } } int u; for (int j = 17; j; j--) for (int i = 1; i <= n; i++){ if (i + bin[j] - 1 > n) break; u = find(f[i][j]); if (sta[u] != i){ merge(f[i][j - 1],f[sta[u]][j - 1]); merge(f[i + bin[j - 1]][j - 1],f[sta[u] + bin[j - 1]][j - 1]); } } int tot = 0; for (int i = 1; i <= n; i++) if (find(f[i][0]) == f[i][0]) tot++; printf("%lld\n",9ll * qpow(10,tot - 1) % P); return 0; }
相关文章推荐
- 【BZOJ4569】[Scoi2016]萌萌哒 倍增+并查集
- BZOJ 4569: [Scoi2016]萌萌哒 倍增思维并查集
- BZOJ 4569: [Scoi2016]萌萌哒 [并查集 倍增]
- BZOJ 4569: [Scoi2016]萌萌哒【倍增并查集
- 4569: [Scoi2016]萌萌哒 倍增+并查集
- BZOJ 4569: [Scoi2016]萌萌哒 ST表 并查集
- bzoj 4569: [Scoi2016]萌萌哒 ST表+并查集
- [BZOJ 4569][SCOI 2016] 萌萌哒 区间并查集(ST表思想)
- BZOJ 4569 [Scoi2016]萌萌哒 | ST表 并查集
- bzoj4569 [Scoi2016]萌萌哒 (st表 维护 并查集)
- 【bzoj4569】【SCOI2016】【萌萌哒】【st表+并查集】
- BZOJ 4569 [Scoi2016]萌萌哒 ——ST表 并查集
- [BZOJ]4569 [SCOI2016] 萌萌哒 并查集神题
- 【BZOJ 4569】【SCOI】【萌萌哒】【并查集】【倍增均摊优化】
- bzoj4569: [Scoi2016]萌萌哒【稀疏表+并查集】
- 【bzoj 4569】[Scoi2016]萌萌哒 (并查集)
- bzoj4569: [Scoi2016]萌萌哒
- bzoj 4569: [Scoi2016]萌萌哒
- [BZOJ4569][Scoi2016]萌萌哒(并查集+st表)
- 【BZOJ 4569】 4569: [Scoi2016]萌萌哒 (倍增+并查集)