Counting Intersections

Counting Intersections

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

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.

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.

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

分析:对于横向线段只保留两个端点并记录类型,对竖向线段保留整个线段;

   离散化并排序,遍历竖向线段,对横向端点树状数组更新;

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <list>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define Lson L, mid, rt<<1
#define Rson mid+1, R, rt<<1|1
const int maxn=2e5+10;
const int dis[4][2]={{0,1},{-1,0},{0,-1},{1,0}};
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
int n,m,k,t,x[maxn],y[maxn],p[maxn],xcnt,ycnt,id,idx;
ll ans;
multiset<int>s;
struct node
{
    int x,low,high;
    bool operator<(const node&p)const
    {
        return x<p.x;
    }
}a[maxn];
struct node1
{
    int x,y,type;
    bool operator<(const node1&p)const
    {
        return x<p.x;
    }
}g[maxn];
int get(int x)
{
    int sum=0;
    for(int i=x;i;i-=(i&(-i)))
        sum+=p[i];
    return sum;
}
void add(int x,int y)
{
    for(int i=x;i<=maxn-5;i+=(i&(-i)))
        p[i]+=y;
}
int main()
{
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        xcnt=ycnt=id=idx=0;
        ans=0;
        memset(p,0,sizeof(p));
        scanf("%d",&n);
        rep(i,1,n)
        {
            int b,c,d,e;
            scanf("%d%d%d%d",&b,&c,&d,&e);
            if(c>e)swap(c,e);
            if(b>d)swap(b,d);
            if(b==d)
            {
                x[++xcnt]=a[++id].x=b;
                y[++ycnt]=a[id].low=c;
                y[++ycnt]=a[id].high=e;
            }
            else
            {
                x[++xcnt]=b;
                x[++xcnt]=d;
                y[++ycnt]=c;
                g[++idx].x=b;
                g[idx].y=c;
                g[idx].type=0;
                g[++idx].x=d;
                g[idx].y=e;
                g[idx].type=1;
            }
        }
        sort(x+1,x+xcnt+1);
        sort(y+1,y+ycnt+1);
        sort(a+1,a+id+1);
        sort(g+1,g+idx+1);
        int num1=unique(x+1,x+xcnt+1)-x-1;
        int num2=unique(y+1,y+ycnt+1)-y-1;
        rep(i,1,id)
        {
            a[i].x=lower_bound(x+1,x+num1+1,a[i].x)-x;
            a[i].low=lower_bound(y+1,y+num2+1,a[i].low)-y;
            a[i].high=lower_bound(y+1,y+num2+1,a[i].high)-y;
        }
        rep(i,1,idx)
        {
            g[i].x=lower_bound(x+1,x+num1+1,g[i].x)-x;
            g[i].y=lower_bound(y+1,y+num2+1,g[i].y)-y;
        }
        int now=1;
        rep(i,1,id)
        {
            while(now<=idx&&g[now].x<=a[i].x)
            {
                if(g[now].type==0)add(g[now].y,1);
                else {
                        if(g[now].x!=a[i].x)
                        add(g[now].y,-1);
                        else s.insert(g[now].y);
                }
                now++;
            }
            ans+=get(a[i].high)-get(a[i].low-1);
            for(int x:s)add(x,-1);
            s.clear();
        }
        printf("%lld\n",ans);
    }
    //system("Pause");
    return 0;
}
时间: 2024-07-29 17:00:28

Counting Intersections的相关文章

HDU 5862 Counting Intersections

题目:Counting Intersections 链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 题意:给出n 条平行于坐标轴的线段,问这些线段有多少交点(题目保证没有两条线段共享一个端点.保证没有重叠.保证线段长度大于0)n范围10万 思路: 将n 条线段2n 个点按x 排序,然后当遇到一个横向的左端点时,对应的y++,遇到右端点,y--,遇到竖线,交点数目加上 下端点到上端点 之间的y 的和.离散化加树状数组可做.要注意细节,

HDU 5862 Counting Intersections (离散化+扫描线+树状数组)

题意:给你若干个平行于坐标轴的,长度大于0的线段,且任意两个线段没有公共点,不会重合覆盖.问有多少个交点. 析:题意很明确,可是并不好做,可以先把平行与x轴和y轴的分开,然后把平行y轴的按y坐标从小到大进行排序,然后我们可以枚举每一个平行x轴的线段, 我们可以把平行于x轴的线段当做扫描线,只不过有了一个范围,每次要高效的求出相交的线段数目,可以用一个优先队列来维护平行y轴的线段的上坐标, 如果在该平行于x轴的范围就给相应的横坐标加1,这样就很容易想到是用树状数组来维护,然后每次求出最左边和最右边

2016暑假多校联合---Counting Intersections

原题链接 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

【HDU5862】Counting Intersections

题意 有n条线段,且都平行于坐标轴.对于每条线段,给出两个端点的坐标.问一共有多少个线段的交点. 分析 最最简单的扫描法了.用线段树或者树状数组都可以. 由题目可知,线段只有两种,要么平行于x轴要么平行于y轴.而交点只能是两个不平行的线段产生的. 所有我们以一条平行于x轴的线为扫描线,从下向上扫.先把横坐标进行离散化,然后把平行于y轴的线段拆成上下两个端点.当扫到下端点的时候就在它横坐标+1,当扫到上端点的时候,就在它横坐标-1.对于每一条平行于x轴的线,则将左右端点内的值相加.就酱~ 这里一个

HDU 5862Counting Intersections

Counting Intersections Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 51    Accepted Submission(s): 18 Problem Description Given some segments which are paralleled to the coordinate axis. You

HDU 5862(离散化+树状数组)

Problem Counting Intersections 题目大意 给定n条水平或竖直的线段,统计所有线段的交点个数. (n<=100000) 解题分析 首先将线段离散化. 然后将所有线段按照横坐标的顺序,按照先插入再查找再删除的顺序进行操作. 对于横线 如果是左端点,则将其纵坐标加1,右端点则减1,对于竖线直接求和就行了. 参考程序 1 #include <map> 2 #include <set> 3 #include <stack> 4 #include

UVA - 12075 Counting Triangles

Description Triangles are polygons with three sides and strictly positive area. Lattice triangles are the triangles all whose vertexes have integer coordinates. In this problem you have to find the number of lattice triangles in anMxN grid. For examp

POJ 2386 Lake Counting 搜索题解

简单的深度搜索就可以了,看见有人说什么使用并查集,那简直是大算法小用了. 因为可以深搜而不用回溯,故此效率就是O(N*M)了. 技巧就是增加一个标志P,每次搜索到池塘,即有W字母,那么就认为搜索到一个池塘了,P值为真. 搜索过的池塘不要重复搜索,故此,每次走过的池塘都改成其他字母,如'@',或者'#',随便一个都可以. 然后8个方向搜索. #include <stdio.h> #include <vector> #include <string.h> #include

Counting Divisors HDU - 6069

Counting Divisors HDU - 6069 题意:给定区间[a,b]和k,求xk有多少因子(x属于[a,b]),求和. 题解:http://blog.csdn.net/zlh_hhhh/article/details/76680641 a.b最大可达到1e12,但是b-a<1e6. 一开始愚蠢的一个一个分解然后去求有多少因子然后求和,范围那么大裸裸的超时啊! 可以枚举素数,对每一个素数,把区间内所有可以分解的进行分解. 最后再求和. 1 #include <bits/stdc++