Nested Segments
time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given n segments on a line. There are no ends of some segments that coincide. For each segment find the number of segments it contains.

Input

The first line contains a single integer n (1 ≤ n ≤ 2·105) — the number of segments on a line.

Each of the next n lines contains two integers li and ri ( - 109 ≤ li < ri ≤ 109) — the coordinates of the left and the right ends of the i-th segment. It is guaranteed that there are no ends of some segments that coincide.

Output

Print n lines. The j-th of them should contain the only integer aj — the number of segments contained in the j-th segment.

Examples
input

Copy
4
1 8
2 3
4 7
5 6
output

Copy
3
0
1
0
input

Copy
3
3 4
1 5
2 6
output

Copy
0
1
1

题意:一条线上有n条直线,没有两个线段有相同的端点,要求每个线段各自包含了多少线段

下面有2种做法

思路1:

记录下右端点的坐标,记录下右端点的坐标,将右端点离散化,用树状数组维护右端点数量前缀和,
给左端点升序排序,从最左边的左端点开始找,
因为左端点升序,所以当前左端点要比所有右端点都小(一开始是满足的,接着我们要不断删去右端点来维护这种状态),当前左端点也比它后面的要小,如果它后面的左端点对应的右端点小于当前右端点,则那条线段是包含在当前线段中的),看当前这个右端点之前有多少个右端点就可知道当前这个线段包含了多少线段
因为我们要保证当前左端点要比所有右端点小才能使得只需统计当前右端点之前有多少右端点就能知道当前这个线段包含了多少线段,如果到了下一个左端点,则上一个线段就不包含在下一个线段中了,因此如果到了下一个左端点就要删掉上一个右端点,所以要删掉当前这个已经找过的右端点

思路2:

记录下右端点的坐标,记录下右端点的坐标,将右端点离散化,用树状数组维护右端点数量前缀和,
给左端点降序排序,从最右边的左端点开始找
因为左端点降序排序,所以当前左端点后都没有比它大的未计算过的左端点,如果比它大的左端点被计算过了且那个左端点对应的右端点比现在这个左端点对应的右端点小,则那条线段必定被当前线段包含,所以按左端点降序的顺序添加对应的右端点,可以保证当前没有右端点比当前左端的小

总结:

两种思路的共同点都是要保证当前左端点之前没有比它小的右端点,这样就只需要统计当前左端点对应的右端点之前有多少个右端点就可以知道当前这条线段包含了多少线段,他们的不同点在于思路1是提前把所有的右端的都加进去了,每次查询的时候再删,而思路2是先从最大的左端点开始添加右端点

思路1代码:

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int amn=2e5+;
int bit[amn],n,tp,b[amn];
struct node{
int l,r,id;
} a[amn];
int ans[amn],jg[amn],pos;
map<ll,int> mp;
bool cmp(node a,node b){
if(a.r==b.r)return a.r<b.r;
return a.l<b.l;
}
int sum(int i){
int s=;
while(i){
s+=bit[i];
i-=i&-i;
}
return s;
}
void add(int i,int x){
while(i<=tp){
bit[i]+=x;
i+=i&-i;
}
}
int main(){
ios::sync_with_stdio();
cin>>n;
tp=;
for(int i=;i<=n;i++){
a[i].id=i; ///记录原始顺序
cin>>a[i].l>>a[i].r;
b[++tp]=a[i].r; ///记录下右端点的坐标
ans[i]=; ///初始化答案数组
}
sort(b+,b++tp); ///给右端点的坐标排序
int mtp=;
for(int i=;i<=tp;i++){
mp[b[i]]=mtp; ///将右端点离散化
mtp++;
}
for(int i=;i<=n;i++){
add(mp[a[i].r],); ///用树状数组维护右端点数量前缀和
}
sort(a+,a++n,cmp); ///给左端点升序排序,从最左边的左端点开始找
for(int i=;i<=n;i++){
ans[a[i].id]=sum(mp[a[i].r]-); ///因为左端点升序,所以当前左端点要比所有未计算过的右端点都小(一开始是满足的,接着我们要不断删去右端点来维护这种状态),当前左端点也比它后面的要小,如果它后面的左端点对应的右端点小于当前右端点,则那条线段是包含在当前线段中的),看当前这个右端点之前有多少个右端点就可知道当前这个线段包含了多少线段
add(mp[a[i].r],-); ///因为我们要保证当前左端点要比所有右端点小才能使得只需统计当前右端点之前有多少右端点就能知道当前这个线段包含了多少线段,如果到了下一个左端点,则上一个线段就不包含在下一个线段中了,因此如果到了下一个左端点就要删掉上一个右端点,所以要删掉当前这个已经找过的右端点
}
for(int i=;i<=n;i++){
printf("%d\n",ans[i]);
}
}
/***
一条线上有n条直线,没有两个线段有相同的端点,要求每个线段各自包含了多少线段
记录下右端点的坐标,记录下右端点的坐标,将右端点离散化,用树状数组维护右端点数量前缀和,
给左端点升序排序,从最左边的左端点开始找,
因为左端点升序,所以当前左端点要比所有未计算过的右端点都小(一开始是满足的,接着我们要不断删去右端点来维护这种状态),当前左端点也比它后面的要小,如果它后面的左端点对应的右端点小于当前右端点,则那条线段是包含在当前线段中的),看当前这个右端点之前有多少个右端点就可知道当前这个线段包含了多少线段
因为我们要保证当前左端点要比所有右端点小才能使得只需统计当前右端点之前有多少右端点就能知道当前这个线段包含了多少线段,如果到了下一个左端点,则上一个线段就不包含在下一个线段中了,因此如果到了下一个左端点就要删掉上一个右端点,所以要删掉当前这个已经找过的右端点
***/

思路2代码:

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int amn=2e5+;
int bit[amn],n,tp,b[amn];
struct node{
int l,r,id;
} a[amn];
int ans[amn],jg[amn],pos;
map<ll,int> mp;
bool cmp1(node a,node b){
if(a.r==b.r)return a.r>b.r;
return a.l>b.l;
}
int sum(int i){
int s=;
while(i){
s+=bit[i];
i-=i&-i;
}
return s;
}
void add(int i,int x){
while(i<=tp){
bit[i]+=x;
i+=i&-i;
}
}
int main(){
ios::sync_with_stdio();
cin>>n;
tp=;
for(int i=;i<=n;i++){
a[i].id=i; ///记录原始顺序
cin>>a[i].l>>a[i].r;
b[++tp]=a[i].r; ///记录下右端点的坐标
ans[i]=; ///初始化答案数组
}
sort(b+,b++tp); ///给右端点的坐标排序
int mtp=;
for(int i=;i<=tp;i++){
mp[b[i]]=mtp; ///将右端点离散化
mtp++;
}
sort(a+,a++n,cmp1); ///给左端点降序排序,从最右边的左端点开始找
for(int i=;i<=n;i++){
add(mp[a[i].r],); ///因为左端点降序排序,所以当前左端点后都没有比它大的未计算过的左端点,如果比它大的左端点被计算过了且那个左端点对应的右端点比现在这个左端点对应的右端点小,则那条线段必定被当前线段包含,所以按左端点降序的顺序添加对应的右端点,可以保证当前没有右端点比当前左端的小
ans[a[i].id]=sum(mp[a[i].r]-);
}
for(int i=;i<=n;i++){ ///两种思路的共同点都是要保证当前左端点之前没有比它小的右端点,这样就只需要统计当前左端点对应的右端点之前有多少个右端点就可以知道当前这条线段包含了多少线段,他们的不同点在于思路1是提前把所有的右端的都加进去了,每次查询的时候再删,而思路2是先从最大的左端点开始添加右端点
printf("%d\n",ans[i]);
}
}
/***
一条线上有n条直线,没有两个线段有相同的端点,要求每个线段各自包含了多少线段
记录下右端点的坐标,记录下右端点的坐标,将右端点离散化,用树状数组维护右端点数量前缀和,
给左端点降序排序,从最右边的左端点开始找
因为左端点降序排序,所以当前左端点后都没有比它大的未计算过的左端点,如果比它大的左端点被计算过了且那个左端点对应的右端点比现在这个左端点对应的右端点小,则那条线段必定被当前线段包含,所以按左端点降序的顺序添加对应的右端点,可以保证当前没有右端点比当前左端的小
两种思路的共同点都是要保证当前左端点之前没有比它小的右端点,这样就只需要统计当前左端点对应的右端点之前有多少个右端点就可以知道当前这条线段包含了多少线段,他们的不同点在于思路1是提前把所有的右端的都加进去了,每次查询的时候再删,而思路2是先从最大的左端点开始添加右端点
***/

[离散化+树状数组]CodeForces - 652D Nested Segments的更多相关文章

  1. Code Forces 652D Nested Segments(离散化+树状数组)

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

  2. CodeForces 540E - Infinite Inversions(离散化+树状数组)

    花了近5个小时,改的乱七八糟,终于A了. 一个无限数列,1,2,3,4,...,n....,给n个数对<i,j>把数列的i,j两个元素做交换.求交换后数列的逆序对数. 很容易想到离散化+树 ...

  3. HDU 5862 Counting Intersections(离散化+树状数组)

    HDU 5862 Counting Intersections(离散化+树状数组) 题目链接http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 D ...

  4. Ultra-QuickSort(归并排序+离散化树状数组)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 50517   Accepted: 18534 ...

  5. CodeForces 652D Nested Segments

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

  6. BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组

    BZOJ_4627_[BeiJing2016]回转寿司_离散化+树状数组 Description 酷爱日料的小Z经常光顾学校东门外的回转寿司店.在这里,一盘盘寿司通过传送带依次呈现在小Z眼前.不同的寿 ...

  7. poj-----Ultra-QuickSort(离散化+树状数组)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 38258   Accepted: 13784 ...

  8. hdu 3015 Disharmony Trees (离散化+树状数组)

    Disharmony Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  9. 【bzoj4627】[BeiJing2016]回转寿司 离散化+树状数组

    题目描述 给出一个长度为n的序列,求所有元素的和在[L,R]范围内的连续子序列的个数. 输入 第一行包含三个整数N,L和R,分别表示寿司盘数,满意度的下限和上限. 第二行包含N个整数Ai,表示小Z对寿 ...

随机推荐

  1. 全栈新视觉——前后端分离

    1234 前端工程化从单纯的 HTML/CSS/JavaScript,到 gulp/webpack 以及 node.js.可能还需要其他的插件 sass.less.vue.react.angular. ...

  2. OpenSSL 生成自定义证书

    前言 本文用来记录通过OpenSSL生成自定义证书并在浏览器设置可信任 准备 Linux CentOS7 系统 nginx 1.12.2 Windows 10 IE 11 chrome 71 Open ...

  3. <pre>标签的使用

    做做笔记.碰见了一个网站,显示代码的时候自带语法高亮,这很新鲜.它的代码被pre标签包裹,原本以为pre标签下的所有的内容会以文本原来的样式输出,特意查了查发现它依然支持html标签. 先来个菜鸟教程 ...

  4. java快速开发平台可视化开发表单

    XJR java快速开发平台,简单的理解就是:开发人员以某种编程语言或者某几种编程语言(比如:目前流行的多种web技术,包括springboot, JPA,Druid, Activiti,Lombok ...

  5. 一起了解 .Net Foundation 项目 No.11

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. Microsoft Web ...

  6. 在ASP.NET Core Mvc 集成MarkDown

    这几天在做文章编辑,首先就想到了markdown,它比其它的都要新,而且很好用,相对于其它的html编辑器,好久不更新,要好得多,哦~对了我现在已经用上新版的Edge了,经过很多朋友测试,性能比谷歌浏 ...

  7. 正式学习MVC 04

    1.ActionResult ActionResult是一个父类, 子类包括了我们熟知的 ViewResult 返回相应的视图 ContentResult  返回字符串 RedirectResult( ...

  8. 使用 Hexo 创建项目文档网站

    当我们发布一个开源项目的时候,最重要的事情之一就是要创建项目文档.对使用项目的用户来说,文档是非常有必要的,通常我们可以使用下面这些方式来创建文档: GitHub Wiki:在 Github 上我们可 ...

  9. 组件化思路:以selection为例子,使用prop-types实现组件化控制,重用

    需求 书接上文,UI 积累之select section 这里又来两个需求了. 当我点击选择了option后,我应该看到的是我选择的option的内容 多例重用,即同样是个selection,我只是需 ...

  10. 负载均衡框架 ribbon 一

    Ribbon开源地址:https://github.com/Netflix/ribbon/wiki/Getting-Started 1.Ribbon简介 负载均衡框架,支持可插拔式的负载均衡规则 支持 ...