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 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...
随机推荐
- hdu 1044(bfs+状压)
非常经典的一类题型 没有多个出口.这里题目没有说清楚 Collect More Jewels Time Limit: 2000/1000 MS (Java/Others) Memory Limi ...
- grub rescue修复引导项
1.需要先找到linux系统盘所在到目录 grub rescue > ls 然后依次 ls (hd0,msdosX)/ 假如我们到系统在msdos2 2.输入 set root=(hd0,msd ...
- 51nod1486 大大走格子
容斥定理+dp...妈呀#1rp耗尽了难怪最近那么衰... #include<cstdio> #include<cstring> #include<cctype> ...
- 基于Flume的美团日志收集系统(一)架构和设计
美团的日志收集系统负责美团的所有业务日志的收集,并分别给Hadoop平台提供离线数据和Storm平台提供实时数据流.美团的日志收集系统基于Flume设计和搭建而成. <基于Flume的美团日志收 ...
- RPi 2B Android telnet ssh
/*********************************************************************** * RPi 2B Android telnet ssh ...
- OK335xS ethtool 移植
/******************************************************************* * OK335xS ethtool 移植 * 声明: * 由于 ...
- Java 炫舞按键功能 DancingPlay (整理)
/** * Java 炫舞按键功能 DancingPlay (整理) * 2016-1-2 深圳 南山平山村 曾剑锋 * * 设计声明: * 1.本次设计是模仿QQ炫舞类游戏,当图标到红色的检测区域时 ...
- HDU 5335 Walk Out (BFS,技巧)
题意:有一个n*m的矩阵,每个格子中有一个数字,或为0,或为1.有个人要从(1,1)到达(n,m),要求所走过的格子中的数字按先后顺序串起来后,用二进制的判断大小方法,让这个数字最小.前缀0不需要输出 ...
- [原创] Ubuntu Linux 安装Eclipse
一 安装JDK 1.下载 JDK 7从http://www.oracle.com/technetwork/java/javasebusiness/downloads/选择下载JDK的最新版本 JDK ...
- jquery事件学习笔记(转载)
一.页面载入1.ready(fn)当DOM载入就绪可以查询及操纵时绑定一个要执行的函数.这是事件模块中最重要的一个函数,因为它可以极大地提高web应用程序的响应速度. 简单地说,这个方法纯粹是对向wi ...