bzoj 4569 [SCOI2016]萌萌哒

题解:

学习了一下区间并查集的姿势

区间并查集模板题

考虑暴力并查集维护相同的数字,方案数就是9*10^(cnt-1) (cnt为连通块个数)

然后考虑用ST表的方式维护并查集

fa[x][k]=y表示[x,x+(1<<k)-1]的区间与[y,y+(1<<k)-1]完全相同

每次merge一下就好了

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define maxn 100005
 4 using namespace std;
 5 const ll mod = 1000000007;
 6 int n,m;
 7 int fa[20][maxn];
 8 int find(int k,int x)
 9 {
10     if(fa[k][x]==x)return x;
11     return fa[k][x]=find(k,fa[k][x]);
12 }
13 void merge(int k,int x,int y)
14 {
15     int fx=find(k,x),fy=find(k,y);
16     if(fx==fy)return;
17     fa[k][fx]=fy;
18     if(!k)return;
19     merge(k-1,x,y);
20     merge(k-1,x+(1<<(k-1)),y+(1<<(k-1)));
21 }
22 int main()
23 {
24     scanf("%d%d",&n,&m);
25     for(int j=18;j>=0;--j)
26         for(int i=1;i<=n;++i)fa[j][i]=i;
27     for(int i=1;i<=m;++i)
28     {
29         int l1,r1,l2,r2;
30         scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
31         int k=(int)(log2((double)(r1-l1+1)));
32         merge(k,l1,l2);
33         merge(k,r1-(1<<k)+1,r2-(1<<k)+1);
34     }
35     int cnt=0;
36     for(int i=1;i<=n;++i)if(find(0,i)==i)cnt++;
37     ll ans=9;
38     for(int i=1;i<=cnt-1;++i)ans=ans*10%mod;
39     printf("%lld\n",ans);
40     return 0;
41 }
View Code

 

posted @ 2019-03-24 15:53  幽蝶  阅读(117)  评论(0编辑  收藏  举报