[CF612D] The Union of k-Segments(排序,扫描线)

题目链接:http://codeforces.com/contest/612/problem/D

题意:给n条线段,问覆盖了k次的区间有几个。

扫描线的思想,首先想到的是从左到右扫一遍,遇到出现被覆盖k次的端点,则开始计数,直到覆盖次数小于k为止。

其实可以用线段树做这道题,但是还有更巧妙的办法:

将左端点看作“入”,右端点看作“出”。每一个线段都是一个区间从入到出,入指的是覆盖次数+1,出指的是覆盖次数-1。

按照左端点升序排列,每遇到一个“入”则计数,并且判断当前计数值是不是等于k了,如果等于k,那说明当前“入”的点恰好是一个覆盖k次的区间的起点。

每遇到一个“出”,则判断一下当前点是不是cnt值为k,如果为k,那说明它恰好是一个覆盖k次区间的终点。插入后计数值-1即可。

这样扫描保证每次都是覆盖k次的区间成对出现。

我们排序希望先“入”后“出”,所以根据pair排序的规则,标记位"入"小于"出"即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 typedef long long LL;
 5 typedef pair<LL, LL> pll;
 6 const int maxn = 1000100;
 7 int n, k;
 8 vector<pll> cover;
 9 vector<LL> ret;
10
11 int main() {
12     // freopen("in", "r", stdin);
13     LL x, y;
14     while(~scanf("%d%d",&n,&k)) {
15         cover.clear(); ret.clear();
16         for(int i = 1; i <= n; i++) {
17             scanf("%I64d%I64d",&x,&y);
18             cover.push_back(pll(x, 0));
19             cover.push_back(pll(y, 1));
20         }
21         sort(cover.begin(), cover.end());
22         int cnt = 0;
23         for(int i = 0; i < cover.size(); i++) {
24             if(cover[i].second == 0) {
25                 cnt++;
26                 if(cnt == k) ret.push_back(cover[i].first);
27             }
28             else {
29                 if(cnt == k) ret.push_back(cover[i].first);
30                 cnt--;
31             }
32         }
33         printf("%d\n", ret.size()/2);
34         for(int i = 0; i < ret.size()/2; i++) {
35             printf("%I64d %I64d\n", ret[i<<1], ret[i<<1|1]);
36         }
37     }
38     return 0;
39 }
时间: 2024-10-10 17:03:15

[CF612D] The Union of k-Segments(排序,扫描线)的相关文章

CodeForces 22D Segments 排序水题

题目链接:点击打开链接 右端点升序,取右端点 暴力删边 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> #include <map> #include <set> #include <math.h> using namespace std; #define inf 10

Leetcode23---&gt;Merge K sorted Lists(合并k个排序的单链表)

题目: 合并k个排序将k个已排序的链表合并为一个排好序的链表,并分析其时间复杂度 . 解题思路: 类似于归并排序的思想,lists中存放的是多个单链表,将lists的头和尾两个链表合并,放在头,头向后移动,尾向前移动,继续合并,直到头和尾相等,此时已经归并了一半, 然后以同样的方法又重新开始归并剩下的一半.时间复杂度是O(logn),合并两个链表的时间复杂度是O(n),则总的时间复杂度大概是O(nlogn):合并两个单链表算法可以参考Leetcode21中的解法:http://www.cnblo

合并k个排序链表

题目 合并k个排序链表,并且返回合并后的排序链表.尝试分析和描述其复杂度. 样例 给出3个排序链表[2->4->null,null,-1->null],返回 -1->2->4->null 解题 两两合并 合并ab得到c 合并cd得到e /** * Definition for ListNode. * public class ListNode { * int val; * ListNode next; * ListNode(int val) { * this.val =

九章算法面试题62 合并k个排序数组

九章算法官网-原文网址 http://www.jiuzhang.com/problem/62/ 题目 给出K个排序好的数组,用什么方法可以最快的把他们合并成为一个排序数组? 在线测试本题 http://lintcode.com/en/problem/merge-k-sorted-lists/ 解答 这中题目分布式系统经常运用到,比如来自不同客户端的排序好的链表想要在主服务器上面合并起来. 一般这种题目有两种做法. 第一种做法比较容易想到,就是有点类似于MergeSort的思路,就是分治法.先把k

[leetcode] 23. 合并K个排序链表

23. 合并K个排序链表 这个题算是考察代码功底吧,基本功,对变量与引用的理解. 不多说了,思路跟第21题基本一致,只不过从两个换成了多个 class Solution { public ListNode mergeKLists(ListNode[] lists) { List<ListNode> listNodes = new ArrayList<>(Arrays.asList(lists)); ListNode ans = new ListNode(Integer.MAX_VA

23. 合并K个排序链表

知乎ID: 码蹄疾 码蹄疾,毕业于哈尔滨工业大学. 小米广告第三代广告引擎的设计者.开发者: 负责小米应用商店.日历.开屏广告业务线研发:主导小米广告引擎多个模块重构: 关注推荐.搜索.广告领域相关知识; 题目 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度.示例:输入:[ 1->4->5, 1->3->4, 2->6]输出: 1->1->2->3->4->4->5->6 分析 前面已经做过两个有序链表的合并,只

LeetCode 第23题 合并K个排序链表

/* 23. 合并K个排序链表 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入:[ 1->4->5, 1->3->4, 2->6]输出: 1->1->2->3->4->4->5->6 */ /** * Definition for singly-linked list. public class ListNode { int val; ListNode next; ListNode(int * x

K个排序链表的合并(Hard)

问题来源:选自leetCode 23:合并K个排序链表 问题描述: 题目给定信息: 不确定需要合并的链表的数目,但依然要求我们把给定的这些有序链表合并成一个链表,并且保证合并的链表依然是有序的. 问题分析: 我们可以使用暴力合并的方法,就是不管有多少个链表,先让第一个链表和第二个链表进行合并,合并之后的结果在和第三个链表进行合并,依次进行下去直到把全部的链表全部合并成一个链表,这种方法是最简单最易想到的方法,但是时间复杂度太高了:还有一种方法是把所有链表中的节点值保存到一个数组中,然后对这个数组

LeetCode 23. 合并K个排序链表(Merge Two Sorted Lists)

23. 合并K个排序链表 23. Merge k Sorted Lists 题目描述 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. LeetCode23. Merge k Sorted Lists困难 示例: 输入: [ ??1->4->5, ??1->3->4, ??2->6] 输出: 1->1->2->3->4->4->5->6 Java 实现 public class ListNode { int va