codeforces 612D The Union of k-Segments (sorting)

来源:互联网 发布:mp4网页播放器js代码 编辑:程序博客网 时间:2024/05/16 15:37

好久没写过博客了。。。 这学期开始要好好分配时间了,在一个时间点中不要将精力太过于分散了,这样感觉最后什么都学不到,什么都学不好。。
这学期好好训练!
链接:http://codeforces.com/contest/612/problem/D
题意:
给定n条线段,给出一个k,定义一个点符合条件的是被至少k条线段覆盖到,要求找出一个最小的线段集合,这个集合能够包含所有满足那个条件的点。
(这里要注意这个线段集合中的线段不需要是之前的线段了,只要由一开始给的n条线段的端点集中的元素构成的就可以了。)
思路:
这类型的题目,马上想到之前类似的题目,利用在线段的两端分别做不同的标志位,比如在左端点标记为 +1 ,右端点标记为-1,不是端点的都为0,那么可以从左边加到右边。(这是个经典方法,在一些贪心判断中很常用),从这个类似的角度去思考。
解题方法:
但是这个又有一点点的不一样,这是要求出包含所有满足点的最小线段集,会发现这个线段集中的线段端点肯定都在之前线段端点集中。那么也可以按照之前的方法进行标记,但是这时候只需要将排序将每个端点加起来,加到一个端点的时候,有两种有用的情况
1) 之前是k-1 ,加完变成 k ,那么这个点就是最小线段集中的一个左端点。
2) 之前是k,加完变成了k-1,那么这个点肯定是一个右端点。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;#define M 10000009int n,k;typedef struct{    int num;    int typ;}Node;Node node[M];bool cmp(Node a,Node b){    if(a.num != b.num) return a.num < b.num;    return a.typ > b.typ;}vector< pair<int,int> > ans;int main(){    scanf("%d %d",&n,&k);    int tot = 0;    for(int i = 0;i < n;i++)    {        scanf("%d",&node[tot].num);        node[tot++].typ = 1;        scanf("%d",&node[tot].num);        node[tot++].typ = -1;    }    sort(node,node+tot,cmp); //sort 将左边的点排在前面, 如果一个点既是线段的左端点,又是另一个的右端点,将左端点的放在前面    int cnt = 0;    int op;    for(int i = 0;i < tot;i++)    {        if(cnt == k-1 && node[i].typ == 1) op = node[i].num;         if(cnt == k && node[i].typ == -1)        {            ans.push_back(make_pair(op,node[i].num));        }        cnt += node[i].typ;    }    printf("%d\n",ans.size());    int ss = ans.size();    for(int i = 0;i < ss;i++)    {        printf("%d %d\n",ans[i].first,ans[i].second);    }    return 0;}
0 0
原创粉丝点击