https://www.cnblogs.com/zhuanzhuruyi/p/5890495.html
类似于密码日记本,N个字母排成一列,每一列都有26个字母,均可翻动,例如:d->c,a->z。然后给你m对数(L,R)(L<=R),表示[L,R]之间可以同时向上翻动,且翻动后是相同的类型。问你最后可以出现多少种不同的类型。
例如:abcabc只给你[1,3],那么abcabc==zababc(代表相同类型)
没有可以翻动的区间则有26^N种类型,每当有相邻两列连到一起,指数便少一种,于是问题转化为并查集合并有多少个不相邻的区间(相交不能合并!!!哇了多少次?)
1-3 + 4-5 =1-5 但是1-3 +3-5 !=1-5(可以选择离散化以后再用并查集)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 10000005;
const int mod = 1000000007;
int f[MAXN];
int l,r,cnt;
int find(int u)
{
if (u != f[u])
f[u] = find(f[u]);
return f[u];
}
void merge(int x,int y)
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
{
f[fx] = fy;
cnt++;
}
}
long long mi(int n,int m)
{
long long sum;
while(n)
{
if(n&1)
sum*=m;
m*=m;
n/=2;
}
return sum;
}
int main()
{
int n,m;
while (~scanf("%d%d",&n,&m) )
{
cnt = 0;
for (int i = 0; i <= n; i++)
f[i] = i;//f[i]代表i的祖先是i
for (int i = 1; i <= m; i++)
{
scanf("%d%d",&l,&r);
merge(l-1,r);//并查集合并相邻区间,传值进去的是l-1!!!!!!!!!!
}
printf("%lld\n",mi(n-cnt,26)%mod);
}
return 0;
}