CodeForces - 612D 思维

题意:

给你n个线段和一个整数k,你需要找出来所有能被任意k条线段同时覆盖的区间个数的最小值,并按从左到右的顺序输出每个区间。

 

题解:

对于题目输入的n个线段的左端点L,右端点R,把它们分开放在结构体里面。结构体的值为右端点或者左端点的值,如果这个点是右端点就标记为0,否则标记为1.

然后对结构体排序,如果结构体的值相等就把标记为0的结构体放在前面,否则就按照值从小到大排序

 

然后从0开始对结构体进行遍历,如果遇到右端点那么线段重合数量cnt加1,如果遇到左端点,那么肯定会有一个线段到达了使用的最右边界,就让cnt减1

 

具体见代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<string>
 6 #include<iostream>
 7 #include<cstdlib>
 8 #include<queue>
 9 #define N 1010000
10 #define INF 0x3f3f3f3f
11 #define MOD 100007
12 using namespace std;
13 struct node
14 {
15     int d,sign;
16 } e[2*N];
17 bool cmp(node q,node qq)
18 {
19     if(q.d==qq.d)
20         return q.sign<qq.sign;//0   1 ,0在前
21     return q.d<qq.d;
22 }
23 int lpos[N];
24 int rpos[N];
25 int main()
26 {
27     int cnt,n,k,l,r,le;
28     scanf("%d %d",&n,&k);
29     le=0;
30     for(int i=1; i<=n; i++)
31     {
32         scanf("%d %d",&l,&r);
33         e[le].d=l;
34         e[le++].sign=0;//左端点
35         e[le].d=r;
36         e[le++].sign=1;//右端点
37     }
38     sort(e,e+le,cmp);
39     int num=0;
40     cnt=0;//记录在此点以及之前左端点的出现次数
41     for(int i=0; i<le; i++)
42     {
43         if(!e[i].sign)
44         {
45             cnt++;
46             if(cnt==k)
47                 lpos[num]=e[i].d;
48         }
49         else
50         {
51             cnt--;
52             if(cnt==(k-1))
53                 rpos[num++]=e[i].d;
54         }
55     }
56     printf("%d\n",num);
57     for(int i=0; i<num; i++)
58         printf("%d %d\n",lpos[i],rpos[i]);
59 }

 

posted @ 2020-05-06 09:58  kongbursi  阅读(207)  评论(0编辑  收藏  举报