CF-612D The Union of k-Segments 差分

D. The Union of k-Segments

题意

给出n个线段,以及一个数字k,让求出有哪些线段:线段上所有的点至少被覆盖了k次。

思路

假如忽略掉线段的左右端点范围,肯定是使用差分来维护每个点被覆盖的次数,遍历一遍统计区间。

对于这题,可以发现所有被覆盖k次以及以上的线段,端点肯定是已知的端点。

所以思路就和差分差不多,我们把所有的端点按坐标小到大排序,左端点赋值+1,右端点赋值为-1。如果坐标相同+1排在前面,开始累加,第一个==k的就是一个区间的起点,第一个<k的就是一个区间的终点。

代码

#include<bits/stdc++.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<string>
#include<math.h>
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-14;

struct note
{
    int pos,val;
    note(int a,int b):pos(a),val(b){}
    note(){}
    bool operator <(const note&a)const
    {
        if(pos==a.pos) return val>a.val;
        return pos<a.pos;
    }
}arr[N*2];
int aga[N*2],en[N*2],tot;
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        arr[i]=note(l,1);
        arr[n+i]=note(r,-1);
    }
    sort(arr+1,arr+1+2*n);
    int num=0,flag=0;
    for(int i=1;i<=2*n;i++)
    {
        num+=arr[i].val;
        if(num==k&&flag==0)
        {
            flag=1;
            aga[++tot]=arr[i].pos;
        }
        else if(flag&&num<k)
        {
            en[tot]=arr[i].pos;
            flag=0;
        }
    }
    printf("%d\n",tot);
    for(int i=1;i<=tot;i++)
        printf("%d %d\n",aga[i],en[i]);
    return 0;
}
posted @   Valk3  阅读(192)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示