题目链接:

http://acm.split.hdu.edu.cn/showproblem.php?pid=5862

Counting Intersections

Time Limit: 12000/6000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
#### 问题描述
> Given some segments which are paralleled to the coordinate axis. You need to count the number of their intersection.
>
> The input data guarantee that no two segments share the same endpoint, no covered segments, and no segments with length 0.
#### 输入
> The first line contains an integer T, indicates the number of test case.
>
> The first line of each test case contains a number n(1 For each test case, output one line, the number of intersection.

样例

sample input

2

4

1 0 1 3

2 0 2 3

0 1 3 1

0 2 3 2

4

0 0 2 0

3 0 3 2

3 3 1 3

0 3 0 2

sample output

4

0

题意

给你若干个平行于坐标轴的,长度大于0的线段,且任意两个线段没有公共点,不会重合覆盖。问有多少个交点。

题解

扫描线+树状数组

首先把平行于x轴的线段和平行于y轴的线段分开存。对于平行于y轴的线段,我们按它的上端点排降序,对于平行于x轴的线段,我们按照它们的高度排降序。

然后我们遍历一遍平行于x轴的线段,考虑有多少条线段与当前遍历的平行于x轴的线段所在的直线相交的线段,并且更新到树状数组中,那么与当前平行于x轴的线段相交的垂直线段为sum(r)-sum(l-1),l、r分别为当前线段的左右端点。

那么,如何维护与某条直线相交的垂直线段呢?

由于我们遍历平行于x轴的直线是按高度从高到低的,对于上端点高于当前遍历高度的所有垂直线段都压到树状数组中,并且把它们的下端点(大的优先)压到优先队列中,然后再从优先队列中踢掉下端点大于当前遍历高度的,同时更新树状数组(删除操作)。

由于数据范围比较大,横坐标需要离散化。

代码

#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) ;//cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define reu(i,a,b) for(int i=a;i<=(b);i++) typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8; //start---------------------------------------------------------------------- const int maxn=4e5+10; LL sumv[maxn]; struct Node{
int val,u,v;
Node(int val,int u,int v):val(val),u(u),v(v){}
bool operator < (const Node& tmp) const {
return val>tmp.val;
}
}; bool cmp(const Node& n1,const Node& n2){
return n1.v>n2.v;
} LL sum(int x){
LL ret=0;
while(x>0){
ret+=sumv[x];
x-=(x&-x);
}
return ret;
} void add(int x,int v){
while(x<maxn){
sumv[x]+=v;
x+=(x&-x);
}
} VI ha;
vector<Node> col,row;
int n; void init(){
ha.clear();
col.clear();
row.clear();
clr(sumv,0);
} int main() {
int tc;
scanf("%d",&tc);
while(tc--){ scanf("%d",&n);
init(); rep(i,0,n){
int u1,v1,u2,v2;
scanf("%d%d%d%d",&u1,&v1,&u2,&v2);
if(u1==u2){
if(v1>v2) swap(v1,v2);
col.push_back(Node(u1,v1,v2));
}else{
if(u1>u2) swap(u1,u2);
row.push_back(Node(v1,u1,u2));
}
ha.push_back(u1);
ha.push_back(u2);
} sort(all(ha));
ha.erase(unique(all(ha)),ha.end()); sort(all(col),cmp);
sort(all(row)); priority_queue<pair<int,int> > pq;
int p=0;
LL ans=0;
rep(i,0,row.sz()){
int hi=row[i].val;
bug(hi);
while(p<col.sz()&&col[p].v>=hi){
int id=lower_bound(all(ha),col[p].val)-ha.begin()+1;
pq.push(mkp(col[p].u,id));
add(id,1);
p++;
}
while(!pq.empty()&&pq.top().X>hi){
add(pq.top().Y,-1);
pq.pop();
}
int l=lower_bound(all(ha),row[i].u)-ha.begin()+1;
int r=lower_bound(all(ha),row[i].v)-ha.begin()+1;
ans+=sum(r)-sum(l-1);
} printf("%lld\n",ans);
}
return 0;
} //end----------------------------------------------------------------------- /*
4
1 0 1 1
0 1 2 1
3 1 3 2
1 2 1 3
*/

HDU 5862 Counting Intersections 扫描线+树状数组的更多相关文章

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

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

  2. HDU 5862 Counting Intersections (树状数组)

    Counting Intersections 题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 Description Given ...

  3. Hdu 5862 Counting Intersections(有n条线段,每一条线段都是平行于x轴或者y轴,问有多少个交点+树状数组区间求和单点跟新)

    传送门:Hdu 5862 Counting Intersections 题意:有n条线段,每一条线段都是平行于x轴或者y轴,问有多少个交点 分析: 基本的操作流程是:先将所有的线段按照横树坐标x按小的 ...

  4. hdu 5862 Counting Intersections

    传送门:hdu 5862 Counting Intersections 题意:对于平行于坐标轴的n条线段,求两两相交的线段对有多少个,包括十,T型 官方题解:由于数据限制,只有竖向与横向的线段才会产生 ...

  5. FZU 2225 小茗的魔法阵 扫描线+树状数组

    这个题和一个CF上的找"Z"的题差不多,都是扫描线+树状数组 从右上角的主对角线开始扫描,一直扫到左下角,每次更新,右延伸等于该扫描线的点,注意在其所在的树状数组更新就好了 时间复 ...

  6. hdu 5517 Triple(二维树状数组)

    Triple Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  7. 【BZOJ1818】[Cqoi2010]内部白点 扫描线+树状数组

    [BZOJ1818][Cqoi2010]内部白点 Description 无限大正方形网格里有n个黑色的顶点,所有其他顶点都是白色的(网格的顶点即坐标为整数的点,又称整点).每秒钟,所有内部白点同时变 ...

  8. 【loj6041】「雅礼集训 2017 Day7」事情的相似度 后缀自动机+STL-set+启发式合并+离线+扫描线+树状数组

    题目描述 给你一个长度为 $n$ 的01串,$m$ 次询问,每次询问给出 $l$ .$r$ ,求从 $[l,r]$ 中选出两个不同的前缀的最长公共后缀长度的最大值. $n,m\le 10^5$ 题解 ...

  9. 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询

    题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...

随机推荐

  1. 解决 SSH 不能输入中文的问题

    有些应用的进程名称可能是中文,还有一些应用创建的目录可以也会是中文,在 SSH 上使用 debugserver 没有办法输入中文的进程名称,也没办法在 SSH 上操作中文的目录,网上试了一些方法,不过 ...

  2. linux 命令 sort

    Linux下的sort排序命令详解(一) 1 sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. [zook ...

  3. 使同一个server上不同port的django应用可在同一个浏览器上打开

    如果我们有两个django应用site1和site2同时跑在同一个server的不同端口,同时我们在同一个浏览器的不同tab登录.那么这时就出出现这种情况,当我们登录site2时就会将site1上登录 ...

  4. java爬虫爬取网页内容前,对网页内容的编码格式进行判断的方式

    近日在做爬虫功能,爬取网页内容,然后对内容进行语义分析,最后对网页打标签,从而判断访问该网页的用户的属性. 在爬取内容时,遇到乱码问题.故需对网页内容编码格式做判断,方式大体分为三种:一.从heade ...

  5. 电竞大数据平台 FunData 的系统架构演进

      电竞大数据时代,数据对比赛的观赏性和专业性都起到了至关重要的作用.同样的,这也对电竞数据的丰富性与实时性提出了越来越高的要求. 电竞数据的丰富性从受众角度来看,可分为赛事.战队和玩家数据:从游戏角 ...

  6. 树莓派3B+SimpleCV上连接iPhone4s摄像头

    目的:把iPhone4s当成网络摄像头,通过wifi连接到树莓派上,做为树莓派的摄像头. 1. iPhone4s上安装mini WebCam应用. 很旧的一个app, 没有密码,简单,无广告,免费. ...

  7. 智能家居系统 Home Assistant 系列 --介绍篇

    一. HomeAssistant 是什么? HomeAssistant是构建智慧空间的神器.是一个成熟完整的基于 Python 的智能家居系统,设备支持度高,支持自动化(Automation).群组化 ...

  8. python学习笔记:第10天 函数进阶和作用域

    目录 1. 函数进阶 2. 命名空间 3. 关键字global和nonlocal 1. 函数进阶 动态接收位置参数 之前写的函数都是固定参数的,假设有个函数需要的参数由几十个,一个个写在形参的位置会非 ...

  9. Linux系统下连接校园网Drcom客户端教程(广东工业大学)

    这篇教程写给想要学习Linux系统或者在Linux系统下有需要使用Drcom上网的同学,在我疯狂踩坑,经过n多次的刷机装机实验,体验不同发行版本的linux系统后,终于懂得怎么连接上drcom,想想连 ...

  10. [Java算法分析与设计]--链式堆栈的设计

    在上篇文章当中,我们实现了底层为数组的顺序栈.在我之前的文章中也提到过:以数组为数据结构基础在存储数据方面需要一整块连续的内存来存放数据,一旦遇到需要可以动态扩展的功能需求时如果数据量大可能会给虚拟机 ...