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 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...
随机推荐
- Winform——计算器进制转换
namespace 进制转换2._0 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } p ...
- LA 4794 Sharing Chocolate
大白书中的题感觉一般都比较难,能理解书上代码就已经很不错了 按照经验,一般数据较小的题目,都有可能是用状态压缩来解决的 题意:问一个面积为x×y的巧克力,能否切若干刀,将其切成n块面积为A1,A2,, ...
- 51nod1346 递归
我终于知道我有多么蠢了...推规律根本不带我这么推的...跟51nod那场比赛的傻逼B题一样,想都不想想就打表找规律...智障啊找规律也要按照基本法! //f[1][2]=a[1][2] f[2][1 ...
- iso中第三方框架SDWebImage的使用步骤
一.SDWebImage的使用 1.依赖的框架 * ImageIO.framework * MapKit.framework 2.UIImageView下载图片需要的头文件:UIImageView+W ...
- 编译busybox错误
为了制作一个文件系统,首先要用busybox编译出文件系统所需要的应用程序.在下载了busybox-1.13.0.tar.bz2后,编译出现如下错误: In file included from /o ...
- android linux shell 日期设置
/************************************************************************ android linux shell 日期设置 * ...
- pandas.Panel数据
from pandas import Panel, DataFrame import numpy as np dd = {} for i in range(1, 3): name = 'X' + st ...
- FPGA代码设计规范整理
1.设计中的FIFO.状态机接口需要有异常恢复状态和状态上报机制,格雷码电路防止被综合电路优化掉. a)自行设计的格雷码FIFO(一般用于连续数据流跨时钟域)用Synplify综合时,为了防止被优化需 ...
- XX.frame.origin.x 赋值问题
can't use that myView.frame.origin.x=25.0; 因为.操作 和 = 一起用的话会调用 set方法.所以上式是行不通的. 可以用下面的方式来实现. that I h ...
- Oracle 安装 检查操作系统版本 必须是 5.0 5.1 的解决办法
打开 oraparam.ini文件 添加红色部分 Windows=5.1,5.2,6.1 最下面添加 [Windows-6.1-required]#Minimum display colours fo ...