zoukankan      html  css  js  c++  java
  • codeforces 689 E. Mike and Geometry Problem 组合数学 优先队列

    给定一个函数:

    f([l,r]) = r - l + 1;

    f(空集) = 0;

    即f函数表示闭区间[l,r]的整点的个数

    现在给出n个闭区间,和一个数k

    从n个区间里面拿出k个区间,然后对这k个区间求并集,并求并集的f函数值

    求所有C(n,k)种方案的f函数值之和

    1 <= k <= n <= 200000

    -10^9 <= l <= r <= 10^9

    思路:

    思路其实很容易想到

    对这些区间缩点

    g(i) 表示i这个点代表的区间的点数(即点i实际的点数)

    s(i) 表示多少条线段含有i这个点

    则:

    ans = sigma(C(s[i],k) * g[i]) , 1 <= p <= tot

    在缩点的时候使用优先队列,同时可以得到g,s这2个数组

    代码:

                                                
      //File Name: cf689E.cpp
      //Author: long
      //Mail: 736726758@qq.com
      //Created Time: 2016年07月11日 星期一 18时44分40秒
                                       
    
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    
    #define LL long long
    
    using namespace std;
    
    const int MAXN = 200000 + 3;
    const int MAXN2 = 800000 + 3;
    const int MOD = (int)1e9 + 7;
    const int INF = 0x3f3f3f3f;
    
    struct Line{
        int l,r;
        bool operator<(const Line &a)const{
            if(a.r == r) return a.l < l;
            return a.r < r;
        }
    }line[MAXN];
    
    int g[MAXN2],s[MAXN2];
    LL jie[MAXN2];
    
    void init(){
        jie[0] = 1;
        for(int i=1;i<MAXN2;i++)
            jie[i] = jie[i-1] * i % MOD;
        memset(g,0,sizeof g);
        memset(s,0,sizeof s);
    }
    
    LL qp(LL x,LL y){
        LL res = 1;
        while(y){
            if(y & 1) res = res * x % MOD;
            x = x * x % MOD;
            y >>= 1;
        }
        return res;
    }
    
    LL get_C(int x,int y){
        if(x < 0 || x < y) return 0;
        if(y == 0 || y == x) return 1;
        return jie[x] * qp(jie[y] * jie[x - y] % MOD,MOD - 2) % MOD;
    }
    
    bool cmp(Line x,Line y){
        if(x.l == y.l)
            return x.r < y.r;
        return x.l < y.l;
    }
    
    LL solve(int N,int K){
        sort(line,line+N,cmp);
        line[N].l = INF;
        int tot = 0,sum = 0,now = line[0].l;
        int iter = 0;
        priority_queue<Line> que;
        while(!que.empty()) que.pop();
        while(!(iter == N && que.empty())){
            while(iter < N && line[iter].l <= now){
                que.push(line[iter]);
                sum++;
                iter++;
            }
            int now_r = que.top().r;
            //printf("now_r = %d sum = %d iter = %d
    ",now_r,sum,iter);
            if(now_r < line[iter].l){
                g[++tot] = now_r - now + 1;
                s[tot] = sum;
                now = now_r + 1;
                //puts("1111111");
            }
            else{
                g[++tot] = line[iter].l - now;
                s[tot] = sum;
                now = line[iter].l;
                //puts("222222222222");
            }
            while(sum && que.top().r < now){
                que.pop();
                sum--;
            }
            if(que.empty())
                now = line[iter].l;
        }
        LL ans = 0;
        for(int i=1;i<=tot;i++){
            ans = (ans + get_C(s[i],K) * g[i] % MOD) % MOD;
        }
        return ans;
    }
    
    int main(){
        init();
        int n,k;
        while(~scanf("%d %d",&n,&k)){
            for(int i=0;i<n;i++){
                scanf("%d %d",&line[i].l,&line[i].r);
            }
            printf("%d
    ",(int)solve(n,k));
        }
        return 0;
    }
  • 相关阅读:
    联合主键有什么用?
    在Spring Boot中使用数据库事务
    Integer.valueOf
    Linux上安装Zookeeper以及一些注意事项
    一个开源的会议管理系统,适合初学者练手(老司机请忽略)
    一个开源的会议管理系统,适合初学者练手(老司机请忽略)
    IntelliJ IDEA中创建Web聚合项目(Maven多模块项目)
    从高考到程序员之毕业流水帐
    Nginx+Tomcat搭建集群,Spring Session+Redis实现Session共享
    Shiro中的授权问题(二)
  • 原文地址:https://www.cnblogs.com/-maybe/p/5661428.html
Copyright © 2011-2022 走看看