luogu3295 萌萌哒 (并查集+ST表)

如果给相同的位置连边,最后联通块数是n,最后答案就是$9*10^{n-1}$

但直接连边是$O(n^2)$的

所以事先处理出一个ST表,每次O(1)地给那个ST表连边

最后再一点一点下放,就是把在这层的同一集合的的左儿子连到一个里,右儿子连到一个里

统计最下面那一层的联通块数量就行了

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e5+10,logn=20,P=1e9+7;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 int id[maxn][20],pct,fa[maxn*logn],ch[maxn*logn][2];
16 int N,M;
17 bool flag[maxn*logn];
18 
19 inline int getf(int x){return fa[x]==x?x:fa[x]=getf(fa[x]);}
20 inline void makest(){
21     for(int i=N;i;i--){
22         id[i][0]=++pct;
23         for(int j=0;id[i][j]&&id[i+(1<<j)][j];j++){
24             id[i][j+1]=++pct;
25             ch[id[i][j+1]][0]=id[i][j];
26             ch[id[i][j+1]][1]=id[i+(1<<j)][j];
27         }
28         // printf("%d %d\n",i,id[i][0]);
29     }
30     for(int i=1;i<=pct;i++) fa[i]=i;
31 }
32 
33 inline pa get(int l,int r){
34     int x=log2(r-l+1);
35     return make_pair(id[l][x],id[r-(1<<x)+1][x]);
36 }
37 
38 inline void add(int a,int b){
39     int x=getf(a),y=getf(b);if(x==y) return;
40     fa[x]=y;
41 }
42 
43 int main(){
44     //freopen("","r",stdin);
45     int i,j,k;
46     N=rd(),M=rd();
47     makest();
48     for(i=1;i<=M;i++){
49         int l1=rd(),r1=rd(),l2=rd(),r2=rd();
50         pa a=get(l1,r1),b=get(l2,r2);
51         add(a.first,b.first);add(a.second,b.second);
52     }
53     for(i=17;i;i--){
54         for(j=1;j<=N&&id[j][i];j++){
55             // printf("%d %d %d %d\n",j,i,id[j][i],fa[id[j][i]]);
56             if(id[j][i]!=fa[id[j][i]]){
57                 add(ch[id[j][i]][0],ch[fa[id[j][i]]][0]);
58                 add(ch[id[j][i]][1],ch[fa[id[j][i]]][1]);
59             }
60         }
61     }
62     int cnt=0;
63     for(i=1;i<=N;i++){
64         if(!flag[getf(id[i][0])]) cnt++,flag[getf(id[i][0])]=1;
65     }
66     
67     ll ans=9;
68     for(i=1;i<=cnt-1;i++) ans=(ans*10)%P;
69     printf("%d\n",ans);
70     return 0;
71 }

 

posted @ 2018-10-13 11:13  Ressed  阅读(204)  评论(0编辑  收藏  举报