第二个样例解释:
集合中含有2个区间:一个是[0,2],编号为1,一个是[1,3],编号为2。
集合的子集有4个:
1、空集,集合中区间的并的长度为0
2、{区间1},集合中区间的并的长度为2
3、{区间2},集合中区间的并的长度为2
4、{区间1、区间2},集合中区间的并为[0,3],长度为3
考虑某一个区间对于答案的贡献:
若某个区间没有被其它区间覆盖,则该区间在子集中出现的总次数为:2^(n-1)次(总子集数-去掉该区间的子集总数)
若某个区间被覆盖了1次,即有2个区间重叠,那么该区间在子集中出现总次数为:2^(n-1)+2^(n-2)次(第1个区间在子集中出现的次数+第2个区间在子集中出现且第1个区间不出现的总次数)
…………
可以得到
若该区间被覆盖了k(k>=0)次,即有k+1个区间重叠,得到该区间在所有子集中出现的总次数:2^(n-1)+2^(n-2)+……+2^(n-k-1)
如何统计每一个区间的重叠次数?
对于输入的每一个区间的两个端点,给一个权值,左端点为1,右端点为-1。然后把所有端点按照位置从小到大排序。从左往右扫一遍,累加端点的权值,得到的当前的权值和就是当前所在区间的重叠次数。
累加每个区间的重叠次数*区间长度,即为所求。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef __int64 LL; #define maxn 100005 #define mod 1000000007 struct P{ int x,y; }a[maxn<<1]; LL ans,sum[maxn],p[maxn]; bool cmp(P x,P y) {return x.x<y.x;} int main() { int T,i,n; scanf("%d",&T); p[0]=1; for(i=1;i<maxn;++i) p[i]=p[i-1]*2%mod; while(T--) { scanf("%d",&n); for(i=1;i<=n+n;i+=2){ scanf("%d%d",&a[i].x,&a[i+1].x); a[i].y=1,a[i+1].y=-1; } sum[1]=p[n-1]; for(i=2;i<=n;++i) sum[i]=(sum[i-1]+p[n-i])%mod; sort(a+1,a+n+n+1,cmp); int ans=0,cnt=0; for(i=1;i<n+n;++i){ cnt+=a[i].y; ans=(ans+sum[cnt]*(a[i+1].x-a[i].x)%mod)%mod; } printf("%d\n",ans); } return 0; }