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 }