题意

在某些区间必须一样的情况下,可以组成多少个大数。

思路

将询问区间拆分成 若干个小区间,将 区间与区间 合并,最后计算答案时 将区间的信息下放到点上。
具体的来讲: 表示左端点为位置 ,长度为 的区间所在集合的根的左端点。
最终计算答案时,将所有层的对应端点合并即可,做法是将每层和他的上层合并 即将 合并,将 合并。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5,mod=1e9+7;
int n,m,fa[N][18],ans;

inline int read()
{
    register int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}

int find(int x,int k) 
{
    return fa[x][k]==x?x:fa[x][k]=find(fa[x][k],k);
}

void merge(int x,int y,int k) 
{
    x=find(x,k),y=find(y,k);
    if(x!=y)fa[x][k]=y;
}

int main() 
{
    n=read();m=read();
    int py=floor(log2(n));
    for(int i=1;i<=n;i++)
        for(int k=0;k<=py;k++)
            fa[i][k]=i;            
    for(int i=1;i<=m;i++) 
    {
        int l1=read(),r1=read(),l2=read(),r2=read();
        for(int k=py;~k;k--)
            if(l1+(1<<k)-1<=r1) merge(l1,l2,k),l1+=1<<k,l2+=1<<k;
    }    
    for(int k=py;k;k--)
        for(int i=1;i+(1<<k)-1<=n;i++)
        {
            int pos=find(i,k);
            merge(i,pos,k-1),merge(i+(1<<k-1),pos+(1<<k-1),k-1);
        }
    for(int i=1;i<=n;i++)
        if(fa[i][0]==i) ans=!ans?9:ans*10ll%mod;
    printf("%d",ans);
    return 0;
}