hdu 5862 树状数组 + 扫描线 + 离散化

题意:给你n条线段 ,求有多少个交点。

分析:第一直觉就是扫描线,然后发现要用树状数组维护前缀和。因为坐标大但是点数小,所以考虑离散化。

具体详见代码

#include
#include
#include
#include
typedef long long ll;
using namespace std;
const int maxn = 2e5 +20;
ll BIT[maxn],X[maxn],Y[maxn];
typedef pair P;
typedef pair PI;
struct line
{
	ll x,y,flag;
bool operator < (const line a)
{
	if(y == a.y) return flag < a.flag;
	return y y1)              // 一定要加这一句话  不然会WA
				swap(y0 , y1);
				X[2*i] =x0;
				Y[2*i] = y0;
				Y[2*i+ 1] = y1;
				p[2*i].x = x0;
				p[2*i].y = y0;
				p[2*i].flag = 1;
				p[2*i + 1].x = x1;
				X[2*i + 1] =x1;
				p[2*i + 1].y = y1;
				p[2*i + 1].flag = 4;
			}
			else
			{
				if(x0 > x1)
				swap(x0 , x1);
				p[2*i].x = x0;
				X[2*i] =x0;
				Y[2*i] = y0;
				Y[2*i+ 1] = y1;
				p[2*i].y = y0;
				p[2*i].flag = 2;
				p[2*i + 1].x = x1;
				p[2*i + 1].y = y1;
				X[2*i+1] =x1;
				p[2*i + 1].flag = 3;
			}
		} 
		ll sum = 0;
		sort(X,X + 2*n);
		int k = unique(X,X+2*n) - X;
        for(int i = 0;i<2*n;i++)
        {
        	p[i].x = lower_bound(X , X +k,p[i].x) - X + 1;
		}
		sort(Y,Y + 2*n);
		k = unique(Y,Y+2*n) - Y;
        for(int i = 0;i<2*n;i++)
        {
        	p[i].y = lower_bound(Y , Y +k,p[i].y) - Y + 1;
		}
		sort(p,p+2*n);
		for(int i = 0;i<2*n;i++)
		{
			if(p[i].flag == 1 )
			{
				add(p[i].x,1);
			}
			else if(p[i].flag == 4)	add(p[i].x,-1);
			else	if(p[i].flag == 2)
			{
				sum += - Sum(p[i].x - 1);
			}
			else	sum += Sum(p[i].x);
		}
		printf("%lld\n",sum);
	}
} 

你可能感兴趣的:(hdu 5862 树状数组 + 扫描线 + 离散化)