题面:

传送门

C. Nested Segments

Input file: standard input
Output file: standard output
Time limit: 2 second
Memory limit: 256 megabytes
 
You are given a sequence a1, a2, ..., an of one-dimensional segments numbered 1 through n. Your task is to find two distinct indices i and j such that segment ai lies within segment aj.
Segment [l1, r1] lies within segment [l2, r2] if l1 ≥ l2 and r1 ≤ r2.
Print indices i and j. If there are multiple answers, print any of them. If no answer exists, print -1 -1.
 
Input
The first line contains one integer n (1 ≤ n ≤ 3·10^5) — the number of segments.
Each of the next n lines contains two integers li and ri (1 ≤ li ≤ ri ≤ 10^9) — the i-th segment.
 
Output
Print two distinct indices i and j such that segment ai lies within segment aj. If there are multiple answers, print any of them. If no answer exists, print -1 -1.
 
Example
Input
5
1 10
2 9
3 9
2 3
2 9
Output
2 1
 
Input
3
1 5
2 6
6 20
Output
-1 -1
 
Note
In the first example the following pairs are considered correct:
  • (2, 1), (3, 1), (4, 1), (5, 1) — not even touching borders;
  • (3, 2), (4, 2), (3, 5), (4, 5) — touch one border;
  • (5, 2), (2, 5) — match exactly.
 

题目描述:

题目给出N个区间,分别编号为1-N,要找出哪一个区间会包含另一个区间,输出区间的编号。
 

题目分析:

这道题其实我们可以这样想:一个区间包含另一个区间的特点是什么?题目告诉我们:被包含的区间左端点要大于等于包含区间的左端点,被包含的区间的右端点要小于等于包含区间的右端点:

                               (区间[1,8]和[4,6])
那么我们直接选两个判断吗?题目数据有3*10^5个区间,任选两个区间作比较肯定是会超时的。这时我们就要找突破口,找到比O(n^2)复杂度更小的想法。刚刚特点告诉我们:是被包含区间的必要条件就是左端点要大于等于包含区间的左端点。那么,我们可不可以先把这N个区间按左端点进行从小到大排序,然后比较右端点就行了?排序的时间复杂度用c++ algorithm里面的sort最坏仅是O(nlogn),对于题目的数据量来说是不会超时的。之后,我们怎么进行比较?只要我们从第1-N个区间遍历一次,区间比较右端点的大小:如果发现当前的右端点比之前遍历过的区间的最大右端点要小或相等,就可以输出答案了。因为这时从1-N的方向遍历保证了被包含区间的左端点肯定是大于等于主动包含区间的左端点,这时发现被包含区间的右端点小于等于包含区间的右端点,所以可以直接输出答案:
(对区间按照左端点从小到大排完序后,就是先遍历[1,8]区间,再遍历[4,6]区间)
如果发现当前的右端点比之前遍历过的区间要大,那么更新右端点最远能到哪里,并记录这个区间的编号,为什么要这样做?
 
这里当遍历到[4,9]这个区间时,因为9比7大,所以[4,9]这个区间不可能包含[3,7],但是[4,9]有可能包含后面的区间,而且后面如果有能被[3,7]包含的区间,[4,9]也一定能包含:
([5,6]区间既被[3,7]包含,又被[4,9]包含)
但是可能是这样:
这时[4,9]能包含的区间([5,8]),[3,7]却不能包含。因为像[5,8]这样的区间有个特点:它们的左端点绝对是大于等于之前的区间(已经排好序了,而且我们是按顺序遍历的),那么,我们在选择右端点的时候,就要贪心地选择右端点较大的,还有记录这个右端点来自哪个区间,才能找到我们想要的答案。如果遍历一遍都还没有找到答案的话,就不存在答案:
这里有一点要注意的是:如果有一个区间的右端点要大于之前的之前区间的最大右端点,但是这个区间的左端点和上一个区间的左端点一样的话:
这时候输出答案就好啦,不用继续遍历下去。还要注意题目输出的是“被包含区间编号    包含区间编号”,不要弄反了。
 
 
AC代码:
 1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #include <cmath>
5 #include <set>
6 #include <map>
7 #include <algorithm>
8 #include <utility>
9 using namespace std;
10 const int maxn = 3e5+5;
11 struct node{
12 int l, r; //左右端点
13 int num; //编号
14 };
15 node seg[maxn]; //存放区间
16
17 bool cmp(node a, node b){
18 return a.l < b.l; //使区间按左端点从小到大排序
19 }
20
21 int main(){
22 int n;
23 scanf("%d", &n);
24 for(int i = 1; i <= n; i++){
25 scanf("%d%d", &seg[i].l, &seg[i].r);
26 seg[i].num = i;
27 }
28
29 sort(seg+1, seg+n+1, cmp);
30
31 int max_right = seg[0].r; //最大的右端点
32 int max_i = 0; //最大右端对应区间
33
34 for(int i = 1; i <= n; i++){
35 if(seg[i].r > max_right){
36 if(seg[i].l == seg[i-1].l){
37 cout << seg[i-1].num << " ";
38 cout << seg[i].num << endl;
39 return 0;
40 }
41 else{
42 max_right = seg[i].r; //更新最大右端点
43 max_i = i; //记录位置
44 }
45 }
46 else {
47 cout << seg[i].num << " ";
48 cout << seg[max_i].num << endl;
49 return 0;
50 }
51 }
52 cout << "-1 -1\n";
53 return 0;
54 }
 

Codeforces 976C Nested Segments的更多相关文章

  1. [离散化+树状数组]CodeForces - 652D Nested Segments

    Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  2. codeforces 652D Nested Segments 离散化+树状数组

    题意:给你若干个区间,询问每个区间包含几个其它区间 分析:区间范围比较大,然后离散化,按右端点排序,每次更新树状数组中的区间左端点,查询区间和 注:(都是套路) #include<cstdio& ...

  3. codeforces 652D . Nested Segments 线段树

    题目链接 我们将线段按照右端点从小到大排序, 如果相同, 那么按照左端点从大到小排序. 然后对每一个l, 查询之前有多少个l比他大, 答案就是多少.因为之前的r都是比自己的r小的, 如果l还比自己大的 ...

  4. CodeForces 652D Nested Segments

    离散化+树状数组 先对坐标离散化,把每条线段结尾所在点标1, 询问某条线段内有几条线段的时候,只需询问这段区间的和是多少,询问结束之后再把这条线段尾部所在点标为0 #include<cstdio ...

  5. Educational Codeforces Round 10 D. Nested Segments 离线树状数组 离散化

    D. Nested Segments 题目连接: http://www.codeforces.com/contest/652/problem/D Description You are given n ...

  6. Educational Codeforces Round 10 D. Nested Segments 【树状数组区间更新 + 离散化 + stl】

    任意门:http://codeforces.com/contest/652/problem/D D. Nested Segments time limit per test 2 seconds mem ...

  7. D - Nested Segments CodeForces - 652D (离散化+树桩数组)

    D - Nested Segments CodeForces - 652D You are given n segments on a line. There are no ends of some ...

  8. codeforces 652D D. Nested Segments(离散化+sort+树状数组)

    题目链接: D. Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  9. Educational Codeforces Round 10 D. Nested Segments

    D. Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

随机推荐

  1. spring再学习之基本概念

    二.spring之IOC与DI 注入的方式: set方法注入: 构造方法注入: 字段注入: 注入类型: 值类型注入:8中基本类型 引用类型注入: BeanFaactory是原始接口:功能比较单一. A ...

  2. .NET Core项目自动化测试和代码覆盖率审查

    这篇文章给大家分享一下,如何配置.NET Core项目自动化测试和代码覆盖率审查. 基本知识,请参考这里: https://docs.microsoft.com/en-us/dotnet/core/t ...

  3. Leetcode(206)-反转链表

    反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 思路:反转链表很简 ...

  4. springboot demo(二)web开发demo

    如入门般建立项目,引入依赖: <dependencies> <dependency> <groupId>org.springframework.boot</g ...

  5. u-boot 移植 --->1、u-boot配置(Kbuild)

    早期的U-BOOT的裁剪是没有使用Kbuild工具的,后来就借鉴了Linux的Kbuild同时也是方便使用者裁剪,因为他的原理和Linux内核的配置裁剪原理是相同的.今天拿来分析的U-Boot的版本是 ...

  6. μC/OS-III---I笔记13---中断管理

    中断管理先看一下最常用的临界段进入的函数:进入临界段 OS_CRITICAL_ENTER() 退出临界段OS_CRITICAL_EXIT()他们两个的宏是这样的. 在使能中断延迟提交时: #if OS ...

  7. [转]论基于DSSA的软件架构设计与应用

    [摘要]   去年三月份,我所在的公司启动国网电力用户用电信息采集系统项目,我被任命为项目负责人.国网电力用户用电信息采集系统是国家电网公司坚强智能电网建设的一部分.由于公司之前为南网(主要是广东省) ...

  8. 网易吃鸡 mac 版,没有声音

    网易吃鸡 mac 版,没有声音 bug 声音太小了 客服电话 问题反馈 提交工单 https://gm.163.com/user_help.html?index=5&stypeid=3619 ...

  9. 析构函数 & 构造函数

    析构函数 & 构造函数 C++ 析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数. 析构函数往往用来做"清理 ...

  10. redux & multi dispatch & async await

    redux & multi dispatch & async await 同时发送多个 action, 怎么保证按序返回数据 dispatch multi actions http:/ ...