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

题目大意

  给定n条水平或竖直的线段,统计所有线段的交点个数。 (n<=100000)

解题分析

  首先将线段离散化。

  然后将所有线段按照横坐标的顺序,按照先插入再查找再删除的顺序进行操作。

  对于横线 如果是左端点,则将其纵坐标加1,右端点则减1,对于竖线直接求和就行了。

        注意排序的时候优先处理竖线,因为有竖线刚好和横线左端点相交的情况

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-4
#define maxn 100010
#define MOD 1000000007

int n;
struct node
{
    int x,y1,y2;
    int flag;
    bool operator <(const node & a)const
    {
        return x < a.x || (x == a.x && flag > a.flag);
    }
}cnt[maxn<<1];

map mp;
int a[maxn<<1];
long long c[maxn<<1];
void update(int x,long long add)
{
    while(x < (maxn<<1))
    {
        c[x] += add;
        x += x & (-x);
    }
}
long long get_sum(int x)
{
    long long sum = 0;
    while(x)
    {
        sum += c[x];
        x -= x & (-x);
    }
    return sum;
}
int main()
{
    int t,C = 1;
    scanf("%d",&t);
    while(t--)
    {
        memset(c,0,sizeof(c));
        scanf("%d",&n);
        int k = 0;
        for(int i = 0; i < n; i++)
        {
            int x1,x2,y1,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            if(x1 == x2)
            {
                if(y1 > y2)
                    swap(y1,y2);
                cnt[k].x = x1;
                cnt[k].y1 = y1;
                cnt[k].y2 = y2;
                cnt[k++].flag = 0;
            }
            else
            {
                if(x1 > x2)
                    swap(x1,x2);
                cnt[k].x = x1;
                cnt[k].y1 = y1;
                cnt[k].y2 = y2;
                cnt[k++].flag = 1;
                cnt[k].x = x2+1;
                cnt[k].y1 = y1;
                cnt[k].y2 = y2;
                cnt[k++].flag = 2;
            }
            a[2*i] = y1;
            a[2*i+1] = y2;
        }
        sort(a,a+2*n);
        mp.clear();
        int len = unique(a,a+2*n) - a;
        for(int i = 1; i <= len; i++)
            mp[a[i-1]] = i;
        sort(cnt,cnt+k);
        long long ans = 0;
        for(int i = 0; i < k; i++)
        {
            if(!cnt[i].flag)
                ans += get_sum(mp[cnt[i].y2]) - get_sum(mp[cnt[i].y1]-1);
            else if(cnt[i].flag == 1)
                update(mp[cnt[i].y1],1);
            else
                update(mp[cnt[i].y1],-1);
        }
        printf("%lld\n",ans);
    }
    return 0;
}


你可能感兴趣的:(数据结构—树状数组)