题目链接:

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. ASP.net 加载不了字体Failed to load resource: the server responded with a status of 404 (Not Found)

    在bootstrap下加载不了字体内容.出现下列错误. 1.打开IIS找到部署的网站,点击MIME类型,把.woff和.woff2两个类型分别添加到新类型中,重启网站即可.  

  2. pdf.js 打印出错

    两种方法:1.使用0.8.223版本的pdf.js2.viewer.js中 line 3642 PRINT_OUTPUT_SCALE=1,line 3639 pdfPage.getViewPort(2 ...

  3. c# 在WebBrowser中用SendMessage模拟鼠标点击

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  4. Office 365部分安装及同时安装Visio的方法

    From MWeb Win版本的Office 365安装包默认安装所有组件,没有选择的页面,在安装Office 365后再安装下载的Visio 2016专业版时,会显示计算机上已经安装了即插即用Off ...

  5. C语言编程学习不难学,是你没找对方法!

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  6. 前端框架---jQuery---一分钟下载使用

    这里通过自己手动的方式“做”一个jQuery来使用,需要5步 1. 访问 https://jquery.com 2. 点击download 3. 拉到最下方,点击 JQuery CDN 4. 得到所有 ...

  7. Testing for diversifying selection for two clades with a background clade

    在利用branch-site检测趋同进化的时候 .可以将各个趋同进化枝分别进行检测,分析的时候不去除某一趋同枝系 .在分析的时候,需要去除其他趋同枝系的影响 I have sequences of a ...

  8. 实验五 Java网络编程

    实验五 Java网络编程 实验五 Java网络编程 实验五所涉及的密码学算法及编程思路 ## Java对称加密-DES算法 (1) 获取密钥生成器 KeyGenerator kg=KeyGenerat ...

  9. 20155338 《JAVA程序设计》实验五网络编程与安全实验报告

    20155338 <JAVA程序设计>实验五网络编程安全实验报告 实验内容 实验一: •两人一组结对编程: •结对实现中缀表达式转后缀表达式的功能 MyBC.java •结对实现从上面功能 ...

  10. 【SQLSERVER】如何找出字符串中的数字

    可以通过写自定义函数实现,以下提供两种思路来解决: 1.通过正则匹配,找到字符串中的数字,一个一个拼起来 /*方法一: 一个一个找出来*/ CREATE FUNCTION [dbo].[Fun_Get ...