description

analysis
-
首先把[L,R][L,R][L,R]看成[L,R+1)[L,R+1)[L,R+1),然后把头尾相连的区间视作做操作
-
就是说,如果一个大区间包含一个与它头或尾相连的小区间,就大区间视作拆成小区间和小区间的补集
-
大区间完全包含另若干各区间(头尾不相连),两两没有影响
-
对于搞完后大小为nnn的区间,该区间答案为2n−12^{n-1}2n−1
-
然后每个区间头和尾连起来,并查集做一做,求出一共有kkk个联通块
-
如果原图有mmm个点,则最终答案就是∑i=1k2ni−1=2m−k\sum_{i=1}^{k}2^{{n_i}-1}=2^{m-k}∑i=1k2ni−1=2m−k
-
这个并查集怎么搞自行思考
code
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 10000005
#define MAXM 100005*2
#define mod 1000000007
#define ll long long
#define fo(i,a,b) for (ll i=a;i<=b;++i)
#define fd(i,a,b) for (ll i=a;i>=b;--i)
using namespace std;
ll fa[MAXM],f[MAXM];
bool bz[MAXN];
ll turn[MAXN];
ll n,m,T,tot,cnt;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline ll getfa(ll x)
{
return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
inline void merge(ll x,ll y)
{
ll xx=getfa(x),yy=getfa(y);
if (xx==yy)return;fa[xx]=yy;
}
inline ll pow(ll x,ll y)
{
ll z=1;
while (y)
{
if (y&1)z=z*x%mod;
x=x*x%mod,y>>=1;
}
return z;
}
int main()
{
//freopen("T2.in","r",stdin);
T=read();
while (T--)
{
n=read(),m=read(),tot=cnt=0;
fo(i,1,m*2)fa[i]=i;
memset(bz,1,sizeof(bz));
memset(turn,0,sizeof(turn));
fo(i,1,m)
{
ll l=read(),r=read()+1;
if (bz[l])bz[l]=0,f[++cnt]=l,turn[l]=cnt;
if (bz[r])bz[r]=0,f[++cnt]=r,turn[r]=cnt;
merge(turn[l],turn[r]);
}
memset(bz,1,sizeof(bz));
fo(i,1,cnt)if (bz[getfa(i)])bz[getfa(i)]=0,++tot;
printf("%lld\n",pow(2,cnt-tot));
}
return 0;
}

3454

被折叠的 条评论
为什么被折叠?



