hdu5481Desiderium+区间覆盖次数

Problem Description
There is a set of intervals, the size of this set is n.

If we select a subset of this set with equal probability, how many the expected length of intervals’ union of this subset is?

We assume that the length of empty set’s union is 0, and we want the answer multiply 2n modulo 10^9+7.

Input
The first line of the input is a integer T, meaning that there are T test cases.

Every test cases begin with a integer n ,which is size of set.

Then n lines follow, each contain two integers l,r describing a interval of [l,r].

1≤n≤100,000.

−1,000,000,000≤l≤r≤1,000,000,000.

Output
For every test case output the answer multiply 2n modulo 109+7.

Sample Input

2
1
0 1
2
0 2
1 3

Sample Output

1
7

Hint
For the second sample, the excepted length is 0+2+2+34=74 .

Source
BestCoder Round #57 (div.2)

一个含有n个区间的集合,从该集合中等概率地选取子集,求所有子集中的所有区间的构成的并集长度的和。

第二个样例解释:

集合中含有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。然后把所有端点按照位置从小到大排序。从左往右扫一遍,累加端点的权值,得到的当前的权值和就是当前所在区间的重叠次数。

期望=贡献值/子集数*2^n
对于包含空集的子集=2^n;
所以答案就是贡献值,即 累加每个区间的重叠次数*区间长度,即为所求。
2n1+2n2++2nk1=2n1(2k1)=2n2k
对于区间重叠次数。用到了一个不知道啥的东西,看到别人的题解,好厉害啊。。a[i].x~a[i+1].x的区间的重叠次数就是前i个y的累加和。(仔细想想,其实就是离散化的思想。。)

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#include<set>
#define pi acos(-1.0)
#define EPS 1e-6    //log(x)
#define e exp(1.0); //2.718281828
#define mod 1000000007
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
typedef long long LL;
using namespace std;
struct Node {
    int l,r;
    bool operator <(const Node &b)const {
        return l<b.l;
    }
} a[200005];
LL pow2[100005];
void init() {
    pow2[0]=1;
    for(int i=1; i<100005; i++) pow2[i]=(pow2[i-1]*2)%mod;
}
int main() {
    init();
    int n;
    int t;
    scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        for(int i=0; i<2*n; i=i+2) {
            int l,r;
            scanf("%d %d",&l,&r);
            a[i].l=l;
            a[i].r=1;
            a[i+1].l=r;
            a[i+1].r=-1;
        }
        sort(a,a+2*n);

        /*for(int i=0;i<2*n;i++){
            printf("%d %d\n",a[i].l,a[i].r);
        }稍微观察一下就发现巧妙啊。。6啊。。orz
        */
        LL ans=0;
        int cnt=0;
        for(int i=0; i<2*n-1; i++) {
            cnt+=a[i].r;
            ans=(ans+(pow2[n]-pow2[n-cnt]+mod)*(a[i+1].l-a[i].l))%mod;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

/*
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         I have a dream!A AC deram!!
 orz orz orz orz orz orz orz orz orz orz orz
 orz orz orz orz orz orz orz orz orz orz orz
 orz orz orz orz orz orz orz orz orz orz orz
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值