【扫描线】Educational Codeforces Round 4 D. The Union of k-Segments

http://codeforces.com/contest/612/problem/D

【题解】

http://blog.csdn.net/strokess/article/details/52248062

【题意】

在数轴x上,给定n个线段和一个值k,问被这n条线段覆盖了至少k次的区间有多少个,输出每一个。

【思路】

扫描线思想。把这n个线段的左右端点放在一起从小到大排序,用cnt记录当前区间被覆盖了多少次,遇到左端点cnt++,遇到右端点cnt--,当cnt==k时记录这时的左端点和右端点。

当左端点和右端点相等时先考虑左端点再考虑右端点,具体为什么可以考虑第二个样例。

因此我们可以很方便地用pair实现这一点,用0标记左端点,用1标记右端点。pair默认排序按first优先,second其次。

【Accepted】

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<string>
 5 #include<cstring>
 6 #include<vector>
 7 #include<utility>
 8 
 9 using namespace std;
10 const int maxn=1e6+3;
11 typedef long long ll;
12 const ll mod=1e9+7;
13 
14 vector<pair<int,int> > v;
15 vector<int> ans;
16 int n,k;
17 int main()
18 {
19     while(~scanf("%d%d",&n,&k))
20     {
21         v.clear();
22         ans.clear();
23         for(int i=0;i<n;i++)
24         {
25             int x,y;
26             scanf("%d%d",&x,&y);
27             v.push_back(make_pair(x,0));
28             v.push_back(make_pair(y,1));
29         }
30         sort(v.begin(),v.end());
31         int sz=v.size();
32         int cnt=0;
33         for(int i=0;i<sz;i++)
34         {
35         //    cout<<v[i].first<<" "<<v[i].second<<endl;
36             if(v[i].second==0)
37             {
38                 cnt++;
39                 if(cnt==k)
40                 {
41                     ans.push_back(v[i].first);
42                 }
43             }
44             else
45             {
46                 if(cnt==k)
47                 {
48                     ans.push_back(v[i].first);
49                 }
50                 cnt--;
51             }
52         }
53         printf("%d\n",ans.size()/2);
54         for(int i=0;i<ans.size()/2;i++)
55         {
56             printf("%d %d\n",ans[2*i],ans[2*i+1]);
57         }
58     }
59     return 0;
60  } 
扫描线

 

posted @ 2017-07-11 12:23  shulin15  阅读(190)  评论(0编辑  收藏  举报