The Union of k-Segments CodeForces

来源:互联网 发布:淘宝上的开心保靠谱吗 编辑:程序博客网 时间:2024/06/05 18:08

You are given n segments on the coordinate axis Ox and the number k. The point is satisfied if it belongs to at least k segments. Find the smallest (by the number of segments) set of segments on the coordinate axis Ox which contains all satisfied points and no others.

Input

The first line contains two integers n and k (1 ≤ k ≤ n ≤ 106) — the number of segments and the value of k.

The next n lines contain two integers li, ri ( - 109 ≤ li ≤ ri ≤ 109) each — the endpoints of the i-th segment. The segments can degenerate and intersect each other. The segments are given in arbitrary order.

Output

First line contains integer m — the smallest number of segments.

Next m lines contain two integers aj, bj (aj ≤ bj) — the ends of j-th segment in the answer. The segments should be listed in the order from left to right.

Example

Input
3 2
0 5
-3 2
3 8
Output
2
0 2
3 5
Input
3 2
0 5
-3 3
3 8
Output
1
0 5

题解:
    该题需要离散化,因为按照题意,线段的端点和线都要记录,所以通过*2来离散化。
    两种方法:1.设一个数组,区间更新时,D[l]++;D[r+1]--;
         2.用线段树记录和更新访问次数
#include"stdio.h"#include"cstdio."#include"algorithm"#include"string.h"using namespace std;const int max_n=1e6+1000; int A[max_n],B[max_n];int C[max_n<<2],D[max_n<<2];int sum[max_n<<2],time[max_n<<2];int len;void chang(int n){    len=0;    int i=0;    D[++len]=C[++i];    for(i=2;i<=n;i++)    {        if(C[i]-C[i-1]>1) D[++len]=C[i-1]+1;        if(C[i]!=D[len]) D[++len]=C[i];    }}int EF(int x){    int l=1,r=len,mid;    mid=(l+r)>>1;    while(l<r)    {        if(D[mid]<x)        l=mid+1;        else if(D[mid]>x)        r=mid-1;        else return mid;        mid=(l+r)>>1;    }    return mid;}int main(){    int n,k;    while(scanf("%d%d",&n,&k)!=EOF)    {        int i,j=0;        for(i=1;i<=n;i++)        {            scanf("%d%d",&A[i],&B[i]);            A[i]*=2;            B[i]*=2;            C[++j]=A[i];            C[++j]=B[i];        }        sort(C+1,C+1+j);        chang(j);        memset(sum,0,sizeof(sum));        for(i=1;i<=n;i++)        {            int l=lower_bound(D+1,D+1+len,A[i])-D;//l=EF(A[i]);            int r=lower_bound(D+1,D+1+len,B[i])-D;//r=EF(B[i]);            sum[l]++;sum[r+1]--;        }        int ans=0;        for(i=1;i<=len;i++)        {            ans+=sum[i];            time[i]=ans;            }         int l=1,r=1,ret=0;        int ll[max_n],rr[max_n];        for(l=1;l<=len;l++)        {            r=l;            if(time[l]>=k&&time[r]>=k)            {                while(time[l]>=k&&time[r]>=k&&r<=len-1)                r++;            }            else            continue;            if(r>=len)            {                if(time[l]>=k&&time[r]>=k)                {                    ll[++ret]=D[l]/2;                    rr[ret]=D[r]/2;                    break;                }            }            else            {                ll[++ret]=D[l]/2;                rr[ret]=D[r-1]/2;            }            l=r;        }        printf("%d\n",ret);        for(i=1;i<=ret;i++)        printf("%d %d\n",ll[i],rr[i]);            }}


线段树:
#include"stdio.h"#include"string.h"#include"algorithm"#include"cstdio"using namespace std;const int max_n=1e6+10; int A[max_n<<1],B[max_n<<1];int C[max_n<<2],D[max_n<<2];int lazy[max_n*9],num[max_n*9];int ll[max_n<<1],rr[max_n<<1];int len,k;void chang(int n){    len=0;    int i=0;    D[++len]=C[++i];    for(i=2;i<=n;i++)    {        if(C[i]-C[i-1]>1) D[++len]=C[i-1]+1;        if(C[i]!=D[len]) D[++len]=C[i];    }}int EF(int x){    int l=1,r=len,mid;    mid=(l+r)>>1;    while(l<r)    {        if(D[mid]<x)        l=mid+1;        else if(D[mid]>x)        r=mid-1;        else return mid;        mid=(l+r)>>1;    }    return mid;}void init(int l,int r,int rt){    if(l==r)    {        num[rt]=0;        return ;    }    int mid=(l+r)>>1;    num[rt]=0;    lazy[rt]=0;    init(l,mid,rt<<1);    init(mid+1,r,(rt<<1)|1);}void down(int rt){    lazy[rt<<1]+=lazy[rt];    lazy[(rt<<1)|1]+=lazy[rt];    num[rt<<1]+=lazy[rt];    num[(rt<<1)|1]+=lazy[rt];    lazy[rt]=0;}void update(int L,int R,int val,int l,int r,int rt){    if(l>=L&&r<=R)    {        lazy[rt]+=val;        num[rt]+=val;        return ;    }    if(lazy[rt])    down(rt);    int mid=(l+r)>>1;    if(L<=mid)    update(L,R,val,l,mid,rt<<1);    if(R>mid)    update(L,R,val,mid+1,r,(rt<<1)|1);    num[rt]=min(num[rt<<1],num[(rt<<1)|1]);}int query(int L,int R,int l,int r,int rt){    if(l>=L&&r<=R)    {        if(num[rt]>=k)        return 1;        else return 0;    }    if(lazy[rt])    down(rt);    int val=1;    int mid=(l+r)>>1;    if(L<=mid)    val=min(val,query(L,R,l,mid,rt<<1));    if(R>mid)    val=min(val,query(L,R,mid+1,r,(rt<<1)|1));    return val;}int main(){    int n;    while(scanf("%d%d",&n,&k)!=EOF)    {        int i,j=0;        for(i=1;i<=n;i++)        {            scanf("%d%d",&A[i],&B[i]);            A[i]*=2;            B[i]*=2;            C[++j]=A[i];            C[++j]=B[i];        }        sort(C+1,C+1+j);        chang(j);        init(1,len,1);        for(i=1;i<=n;i++)        {            int l=EF(A[i]);            int r=EF(B[i]);            update(l,r,1,1,len,1);        }        for(i=1;i<=len;i++)        query(i,i,1,len,1);        int l=1,r=1,ret=0;        for(l=1;l<=len;l++)        {            r=l;            if(query(l,r,1,len,1))            {                while(query(l,r,1,len,1)&&r<=len-1)                r++;            }            else            continue;            if(r==len)            {                if(query(l,r,1,len,1))                {                    ll[++ret]=D[l]/2;                    rr[ret]=D[r]/2;                    break;                }            }            else            {                ll[++ret]=D[l]/2;                rr[ret]=D[r-1]/2;            }            l=r;        }        printf("%d\n",ret);        for(i=1;i<=ret;i++)        printf("%d %d\n",ll[i],rr[i]);    }}