解题思路:
考虑暴力就是 O(n2) 用并查集维护那些位置要填的数字相同,若最后有 cnt 个集合,那 ans=9∗10cnt−1 (第一个集合填不能填0)。
考虑类似ST表的方法,第
j
层把每个区间划分成前
处理完所有条件之后,我们会得到
这题中先用ST表思想处理条件,最后统计的方法是很妙的。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=100005,p=1e9+7;
int n,m,ans,fa[20][N],Log[N];
int find(int d,int x)
{
return fa[d][x]==x?x:fa[d][x]=find(d,fa[d][x]);
}
void merge(int d,int x,int y)
{
x=find(d,x),y=find(d,y);
if(x!=y)fa[d][x]=y;
}
int main()
{
//freopen("lx.in","r",stdin);
n=getint(),m=getint();
for(int i=2;i<=n;i++)Log[i]=Log[i>>1]+1;
for(int j=0;j<20;j++)
for(int i=1;i<=n;i++)fa[j][i]=i;
int l1,r1,l2,r2,d,x,y;
while(m--)
{
l1=getint(),r1=getint(),l2=getint(),r2=getint();
d=Log[r1-l1+1];
merge(d,l1,l2),merge(d,r1-(1<<d)+1,r2-(1<<d)+1);
}
for(int j=19;j;j--)
for(int i=1;i+(1<<j-1)<=n;i++)
{
x=i,y=find(j,x);
merge(j-1,x,y);
merge(j-1,x+(1<<j-1),y+(1<<j-1));
}
m=0;
for(int i=1;i<=n;i++)
if(fa[0][i]==i)m++;
ans=9;
for(int i=1;i<m;i++)ans=(ll)ans*10%p;
cout<<ans;
return 0;
}