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 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...
随机推荐
- 函数lock_rec_get_first_on_page
lock结构体 详见 /*********************************************************************//** Gets the first ...
- 多线程操作(循环往listbox中添加数据)
一.先造一个窗体,其中就开始按钮,暂停按钮,以及listbox文本框 二.当点击开始的时候,数据会无限的往listbox中加,为了防止卡住和提升效率,便造了一个新的线程来执行开始操作 namespac ...
- LA 4725 (二分) Airport
题意: 有W.E两个跑道,在每个时刻每个跑道的飞机都从0开始编号,而且每个时刻都有Wi和Ei架飞机到达这两个跑道.而且每个时刻只能选择一个跑道的一架飞机起飞.问如何选择才能使得飞机的最大编号最小.(每 ...
- splay入门
在比较了网上的几份模板的速度之后,发现指针版明显快了很多,但是一敲起来....各种不习惯...所以还是学的hzwer 的数组版... bzoj3223:维护reverse操作就可以了 #include ...
- 漫游Kafka设计篇之性能优化
Kafka在提高效率方面做了很大努力.Kafka的一个主要使用场景是处理网站活动日志,吞吐量是非常大的,每个页面都会产生好多次写操作.读方面,假设每个消息只被消费一次,读的量的也是很大的,Kafka也 ...
- 转:整理一下Entity Framework的查询
Entity Framework是个好东西,虽然没有Hibernate功能强大,但使用更简便.今天整理一下常见SQL如何用EF来表达,Func形式和Linq形式都会列出来(本人更喜欢Func形式). ...
- jquery响应回车事件
简单地记下jquery实现回车事件,代码如下: 全局: $(function(){document.onkeydown = function(e){ var ev = document.all ...
- 【转】Qt数据库总结
转自:http://blog.chinaunix.net/uid-25201977-id-3014100.html #include <QtSql>QT += sql QSqlDataba ...
- uva 11991
STL 使用,,由于数据范围没有 超越极限数据 依旧可以用 vector 搞定: #include<iostream> #include<stdio.h> #include& ...
- Wiz发布cnblog笔记
[转自Wiz官网][插件]发布笔记到博客,更好的博客离线撰写工具 发表于 2011 年 2 月 23 日 由 admin 为知笔记支持绝大部分的博客离线撰写,可以方便地把笔记直接发布为博客. 使用 打 ...