我是靠谱客的博主 包容路人,最近开发中收集的这篇文章主要介绍HDU 5862 Counting Intersections(树状数组+扫描线+离散化) Counting Intersections,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
Counting Intersections
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1296 Accepted Submission(s): 407
Problem 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.
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<=n<=100000), the number of segments. Next n lines, each with for integers, x1, y1, x2, y2, means the two endpoints of a segment. The absolute value of the coordinate is no larger than 1e9.
The first line of each test case contains a number n(1<=n<=100000), the number of segments. Next n lines, each with for integers, x1, y1, x2, y2, means the two endpoints of a segment. The absolute value of the coordinate is no larger than 1e9.
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
Author
BUPT
Source
2016 Multi-University Training Contest 10
题意:
给你几根与坐标轴平行的线,问你产生几个交点。
POINT:
树状数组的区间值是保存了y区间内有几根横线。
把y轴离散化。横线只要看成2个点,和竖线一起依x轴从小到大排序。
然后从左向右扫描,扫描到左端点,就y点+1,右端点就-1,扫描到竖线,就查询竖线上的y区间内右几根横线。(单点修改,区间查询)
注意端点与线重合的情况,优先扫描左端点,然后再扫描竖线,最后是右端点,不然答案会少。画一个右端点和竖线重合的图思考一下。
(就是为了去补这题多校,才去做了很多线段树和树状数组,终于把这题1A了,思考时间也不长,写的很快还没有错,那么线段树和树状数组也就告一段落,下面学习RMQ吧。自己还有很多要学的呢。
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 100050*5;
#define LL long long
struct node//离散纵坐标
{
int x,y1,y2;
int flag;//零代表竖线, 1代表横线左端点 -1右端点
}dian[N];
int haha[N];
int mm;
int yy[N];
int num[N];
int lowbit(int x)
{
return x&-x;
}
void add(int x,int c)
{
while(x<=mm)
{
num[x]+=c;
x+=lowbit(x);
}
}
LL query(int x)
{
LL ans=0;
while(x>=1)
{
ans+=(LL)num[x];
x-=lowbit(x);
}
return ans;
}
int Discretization(int y)
{
return (int)(lower_bound(yy+1,yy+1+mm,y)-yy);
}
bool cmd(node a,node b)
{
if(a.x!=b.x)
return a.x<b.x;
else
return a.flag>b.flag;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
memset(dian,0,sizeof dian);
memset(haha,0,sizeof haha);
memset(yy,0,sizeof yy);
memset(num,0,sizeof num);
int m=0;
int my=0;
for(int i=1;i<=n;i++)
{
int x1,x2,y1,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
if(x1>x2) swap(x1,x2);
if(y1>y2) swap(y1,y2);
if(x1==x2)
{
dian[++m].x=x1;
dian[m].flag=0,dian[m].y1=y1,dian[m].y2=y2;
yy[++my]=y1;
yy[++my]=y2;
}
else
{
dian[++m].x=x1;
dian[m].flag=1,dian[m].y1=dian[m].y2=y1;
dian[++m].x=x2;
dian[m].flag=-1,dian[m].y1=dian[m].y2=y2;
yy[++my]=y1;
}
}
sort(yy+1,yy+1+my);
mm=1;
for(int i=2;i<=my;i++)
{
if(yy[i-1]!=yy[i]) yy[++mm]=yy[i];
}
sort(dian+1,dian+1+m,cmd);
LL ans=0;
for(int i=1;i<=m;i++)
{
if(dian[i].flag==0)//竖线
{
int Y=Discretization(dian[i].y2);
int y=Discretization(dian[i].y1);
ans+=query(Y)-query(y-1);
}
else if(dian[i].flag==-1)//右端点
{
int y=Discretization(dian[i].y1);
add(y,-1);
}
else
{
int y=Discretization(dian[i].y1);
add(y,1);
}
}
printf("%lldn",ans);
}
}
最后
以上就是包容路人为你收集整理的HDU 5862 Counting Intersections(树状数组+扫描线+离散化) Counting Intersections的全部内容,希望文章能够帮你解决HDU 5862 Counting Intersections(树状数组+扫描线+离散化) Counting Intersections所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复