题目链接:

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. 课时6.HTTP协议(理解)

    HTTP是Hypertext Transfer Protocol的缩写,译为:超文本传输协议 什么是协议? 在现实生活中有很多的协议,例如租房协议/买卖协议/离婚协议 无论是什么协议它们都有一个共同点 ...

  2. MongoDB4.0在windows10下的安装与服务配置

    本地安装及网页测试 在官网下载最新的安装文件 下载地址 : https://www.mongodb.com/download-center#community 可以在MongoDB官网选择Commun ...

  3. 学习tp5的第三天(模型)

    一.模型 1.定义基础模型 <?php namespace app\index\model; use think\Model; class User extends Model{ // 设置完整 ...

  4. day1-exercise

    """ Day1 作业 Isabelle/刘佳赐 October 22, 2018 """ """ 1. 变量 ...

  5. JavaScript中使用比较多的两种创建对象的方式

    1.使用组合模式创建对象 原型模式创建对象适合封装方法,构造方法模式创建对象适合封装属性 组合方法缺点:将构造方法和原型分开写 <script type="text/javascrip ...

  6. VIM - 模式简介

    1. 概述 简述 vim 模式 很简单的东西, 随便说说得了 2. 模式们 概述 vim 各个模式 后面的切换, 都是从 标准模式 切换到其他模式 1. Normal Mode 名称 标准模式 / 常 ...

  7. django无法加载样式

    如果运行的环境是win10,那么首先应该考虑是否是如下问题 win10中Django后台admin无法加载CSS等样式 解决: 修改win10的注册表:[win+R输入Regedit] 因为你安装的某 ...

  8. 20155212 实验一《Java开发环境的熟悉》实验报告

    20155212 实验一<Java开发环境的熟悉>实验报告 命令行下Java程序开发 命令创建实验目录 输入mkdir 2051212创建以自己学号命名的文件夹,通过cd 20155212 ...

  9. 20155330 2016-2017-2 《Java程序设计》第二周学习总结

    20155330 2016-2017-2 <Java程序设计>第二周学习总结 教材学习内容总结 学习目标 了解Java编程风格 认识Java的类型与变量 掌握Java流程控制的方法(分支. ...

  10. [FJOI2014]最短路径树问题 长链剖分

    [FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...