HDU - 5862
题意:给你很多条平行于坐标轴的线段,然后求交点的个数。
思路:把平行于x轴的线段看成两个点,进点权值是+1,而出点权值为-1,把平行y轴的线,看作区间查询,注意:
入点和查询在同一个位置,先更新入点,出点和查询在同一个位置,那就先查询。当然首先得离散化y坐标~
代码:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
const int maxn = 1e5 + 10;
struct node
{
int si,sj,pi,pj,w;
node(){}
node(int a,int b,int c,int d,int e)
{si = a; sj = b; pi = c; pj = d; w = e;}
}line[maxn << 1];
int yid[maxn << 1];
int ynum,num,t,n,m;
ll val[maxn << 4];
void init()
{
num = 0; ynum = 1;
memset(val,0,sizeof(val));
}
int getid(int x)
{
return lower_bound(yid + 1,yid + 1 + ynum , x) - yid;
}
bool cmp(node a,node b)
{
if(a.si == b.si)
{
return a.w > b.w;
}
return a.si < b.si;
}
void updata(int id,int l,int r,int u,int v)
{
//cout << l <<" " << r << " " <>1;
if(u <= mid) updata(id << 1, l , mid, u, v);
else updata(id<<1|1, mid + 1, r, u, v);
val[id] = val[id<<1] + val[id<<1|1];
}
ll query(int id,int l,int r,int ql,int qr)
{
if(r < ql || l > qr) return 0;
if(l >= ql && r <= qr) return val[id];
int mid = l+r>>1;
ll ans = 0;
if(ql <= mid) ans += query(id<<1, l , mid, ql , qr);
if(qr > mid) ans += query(id<<1|1,mid+1,r,ql,qr);
return ans;
}
int main()
{
//freopen("D:\\in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();
int anum = 0,bnum = 0;
for(int i = 0; i < n; i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
yid[ynum++] = b, yid[ynum++] = d;
if(b == d)
{
anum++;
if(a > c) swap(a,c);
line[num++] = node(a,b,0,0, 1);
line[num++] = node(c,d,0,0,-1);
}
else
{
bnum++;
line[num++] = node(a,b,c,d,0);
}
}
if(anum == 0 || bnum == 0)
{
printf("0\n");
continue;
}
sort(line, line + num, cmp);
//离散化
sort(yid + 1 , yid + 1 + ynum);
ynum = unique(yid + 1,yid + 1 + ynum) - yid;
ll ans = 0;
for(int i = 0; i < num; i++)
{
int w = line[i].w;
if(w != 0)
{
int id = getid(line[i].sj);
updata(1,1,ynum-1,id,w);
}
else
{
int l = getid(line[i].sj), r = getid(line[i].pj);
if(l > r) swap(l,r);
ll temp = query(1,1,ynum-1,l,r);
ans += temp;
}
}
cout << ans << endl;
}
return 0;
}