HDU 5862 Counting Intersections (树状数组)
Counting Intersections
题目链接:
http://acm.split.hdu.edu.cn/showproblem.php?pid=5862
Description
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.
Input
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
Output
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
Source
2016 Multi-University Training Contest 10
##题意:
给出平面上N条平行于坐标轴的线段. 保证线段没有公共端点,没有覆盖.
求N条线段有多少个交点.
##题解:
对于所有线段按照x坐标排序,将y坐标离散化,在从左到右遍历线段的过程中:
遇到水平线段的左端点时,将其对应y坐标在树状数组中的值+1.
遇到水平线段的(右端点+1)时,将其对应y坐标在树状数组中的值-1.
遇到竖直线段时,查询其纵坐标区间的和,即为这条竖直线段能产生的交点的个数.
注意的几点:
以下代码将水平线段当成两个点来存储,竖直线段当成一个点来存储.
离散化时只需要对y坐标离散.
在排序时,x坐标是第一优先级,其次应该按先水平再竖直排序. 这样可以保证'T'字型情况得到处理.
应该在遇到水平线段右端点+1的位置时才将树状数组中的值-1.
树状数组中的n为需要处理的纵坐标的个数,不是输入的n,务必区分开来.
比赛时想的是区间更新+单点查询,即先将在某条水平线段横坐标区间内竖直线段进行区间更新,这样一来对水平线段的排序就不太好处理,比如投影区间覆盖的情况.
贴一个[线段树+扫描线](http://www.cnblogs.com/zhangchengc919/p/5784725.html)的解法,过几天学习一下:
##代码:
``` cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define eps 1e-8
#define maxn 201000
#define mod 100000007
#define inf 0x3f3f3f3f
#define mid(a,b) ((a+b)>>1)
#define IN freopen("in.txt","r",stdin);
using namespace std;
struct node {
int type; // 0横 1竖
int x, y1,y2;
node() {}
node(int a,int b,int c,int d) {type=a;x=b;y1=c;y2=d;}
bool operator < (const node& b) const {
if(x == b.x) return type < b.type; //先处理横向
return x < b.x;
}
}p[maxn];
int n, cnt;
int c[maxn];
int lowbit(int x) {
return x & (-x);
}
int newn; // 区别于n
void update(int x, int d) {
while(x <=newn) {
c[x] += d;
x += lowbit(x);
}
}
int get_sum(int x) {
LL ret = 0;
while(x > 0) {
ret += c[x];
x -= lowbit(x);
}
return ret;
}
map<int, int> mp;
int pos[maxn], pos_cnt;
int main(int argc, char const *argv[])
{
//IN;
int t; cin >> t;
while(t--)
{
scanf("%d", &n);
mp.clear();
cnt = 0; pos_cnt = 0;
for(int i=1; i<=n; i++) {
int x1,y1,x2,y2; scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
if(y1 == y2) { // hor
if(x1 > x2) swap(x1, x2);
p[++cnt] = node(0, x1, y1, +1);
p[++cnt] = node(0, x2+1, y1, -1); //右端点的下一个位置
pos[++pos_cnt] = y1;
} else { // ver
if(y1 > y2) swap(y1, y2);
p[++cnt] = node(1, x1, y1, y2);
pos[++pos_cnt] = y1;
pos[++pos_cnt] = y2;
}
}
sort(pos+1, pos+1+pos_cnt);
int counts = 0;
for(int i=1; i<=pos_cnt; i++) {
if(!mp[pos[i]]) mp[pos[i]] = ++counts;
}
sort(p+1, p+1+cnt);
LL ans = 0;
newn = counts; //务必与n区分开来
memset(c, 0, sizeof(c));
for(int i=1; i<=cnt; i++) {
if(p[i].type == 0) { // hor
update(mp[p[i].y1], p[i].y2);
} else { // ver
ans += get_sum(mp[p[i].y2]) - get_sum(mp[p[i].y1]-1);
}
}
printf("%lld\n", ans);
}
return 0;
}
HDU 5862 Counting Intersections (树状数组)的更多相关文章
- HDU 3887 Counting Offspring (树状数组+人工模拟栈)
对这棵树DFS遍历一遍,同一节点入栈和出栈之间访问的节点就是这个节点的子树. 因此节点入栈时求一次 小于 i 的节点个数 和,出栈时求一次 小于 i 的节点个数 和,两次之差就是答案. PS.这题直接 ...
- HDU 5862(离散化+树状数组)
Problem Counting Intersections 题目大意 给定n条水平或竖直的线段,统计所有线段的交点个数. (n<=100000) 解题分析 首先将线段离散化. 然后将所有线段按 ...
- HDU 5862 Counting Intersections(离散化+树状数组)
HDU 5862 Counting Intersections(离散化+树状数组) 题目链接http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 D ...
- Hdu 5862 Counting Intersections(有n条线段,每一条线段都是平行于x轴或者y轴,问有多少个交点+树状数组区间求和单点跟新)
传送门:Hdu 5862 Counting Intersections 题意:有n条线段,每一条线段都是平行于x轴或者y轴,问有多少个交点 分析: 基本的操作流程是:先将所有的线段按照横树坐标x按小的 ...
- hdu 5862 Counting Intersections
传送门:hdu 5862 Counting Intersections 题意:对于平行于坐标轴的n条线段,求两两相交的线段对有多少个,包括十,T型 官方题解:由于数据限制,只有竖向与横向的线段才会产生 ...
- HDU 5862 Counting Intersections 扫描线+树状数组
题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 Counting Intersections Time Limit: 12000/ ...
- HDU 5862 Counting Intersections(离散化 + 树状数组)
Counting Intersections Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/ ...
- HDU 5862 Counting Intersections (离散化+扫描线+树状数组)
题意:给你若干个平行于坐标轴的,长度大于0的线段,且任意两个线段没有公共点,不会重合覆盖.问有多少个交点. 析:题意很明确,可是并不好做,可以先把平行与x轴和y轴的分开,然后把平行y轴的按y坐标从小到 ...
- HDU 3333 | Codeforces 703D 树状数组、离散化
HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...
随机推荐
- 【温故知新】C#委托delegate
在c#的学习过程中,学到委托与事件总会迷糊一段时间,迷糊过后自然而就似懂非懂了~,所以最近我打算把以前所学的迷糊过的知识总结,温故知新,总结记录下来. 首先,我们来看一下msdn对委托的定义: del ...
- Machine Learning for hackers读书笔记(九)MDS:可视化地研究参议员相似性
library('foreign') library('ggplot2') data.dir <- file.path('G:\\dataguru\\ML_for_Hackers\\ML_for ...
- [ionic开源项目教程] - 第10讲 新闻详情页的用户体验优化
目录 [ionic开源项目教程] 第1讲 前言,技术储备,环境搭建,常用命令 [ionic开源项目教程] 第2讲 新建项目,架构页面,配置app.js和controllers.js [ionic开源项 ...
- hadoop1常见配置含义
参数 取值 备注 fs.default.name NameNode ...
- 模拟实现STL中的list
#pragma once #include<iostream>using namespace std;#include<assert.h> template<class ...
- Android 源代码自动编译packages/apps
/*************************************************************************** * Android 源代码自动编译packag ...
- pandas.Panel数据
from pandas import Panel, DataFrame import numpy as np dd = {} for i in range(1, 3): name = 'X' + st ...
- C的输入输出函数的基本用法
printf输出函数: printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息. printf()函数的调用格式为: printf("<格式化字符串>& ...
- 广义线性模型 GLM
Logistic Regression 同 Liner Regression 均属于广义线性模型,Liner Regression 假设 $y|x ; \theta$ 服从 Gaussian 分布,而 ...
- aspose.word使用简单方法
概念介绍 使用aspose生成word报表步骤: 加载word模板 提供数据源 填充 加载模板 提供了4种重载方法 public Document(); public Document(Stream ...