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 }