题意
在某些区间必须一样的情况下,可以组成多少个大数。
思路
将询问区间拆分成 若干个小区间,将 区间与区间 合并,最后计算答案时 将区间的信息下放到点上。
具体的来讲: 表示左端点为位置
,长度为
的区间所在集合的根的左端点。
最终计算答案时,将所有层的对应端点合并即可,做法是将每层和他的上层合并 即将 与
合并,将
与
合并。
#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;
}
京公网安备 11010502036488号