树状数组+离散化
Posted linhaitai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组+离散化相关的知识,希望对你有一定的参考价值。
题意:给出n条平行x或y轴的线段,求线段的交点。
分析:
将 平行 x 轴的直线离散化,只记录它的端点,排序,然后就用树状数组查询。
将 平行y的直线按x 的大小排序,遍历,然后就只考虑它左边的点,遇到是左端点的树状数组就在那个点的y处加一,遇到右端点就在其y处减1。
因为它右端点都在直线的左边,就说明左端点也在,就减一抵消之前的加一。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<vector> typedef long long ll; using namespace std; const int max_=400005; struct node1{//开始的直线和后面的平行y轴的直线 int x1,y1,x2,y2; bool operator <(node1 a)const//后面的平行y轴的直线按x排序 { return x1<a.x1; } }edge[max_],c[max_]; struct node2{//离散化平行x轴的直线 int x,y,type; bool operator <(node2 a)const//先按x排序,x相同就左端点优先 { if(x==a.x) return type<a.type; return x<a.x; } }r[max_]; int Hash[max_]; int bit[max_]; void bit_add(int i,int x,int max_n)//树状数组的单点修改 { while(i<max_n) { bit[i]+=x; i+=i&-i; } } ll bit_getsum(int i)//前i项和 { ll ans=0; while(i>0) { ans+=bit[i]; i-=i&-i; } return ans; } int main() { int T; cin>>T; while(T--) { int n; scanf("%d",&n); memset(bit,0,sizeof(bit)); int tot=1; for(int i=0;i<n;i++) { scanf("%d %d %d %d",&edge[i].x1,&edge[i].y1,&edge[i].x2,&edge[i].y2); if(edge[i].x1>edge[i].x2||edge[i].y1>edge[i].y2)//保证左小右大,上大下小 { swap(edge[i].x1,edge[i].x2); swap(edge[i].y1,edge[i].y2); } Hash[tot++]=edge[i].x1; Hash[tot++]=edge[i].y1; Hash[tot++]=edge[i].x2; Hash[tot++]=edge[i].y2; } sort(Hash+1,Hash+tot); tot=unique(Hash+1,Hash+tot)-Hash;//去重 int tot1=0,tot2=0; for(int i=0;i<n;i++) { int x1,y1,x2,y2; x1=lower_bound(Hash+1,Hash+tot,edge[i].x1)-Hash; y1=lower_bound(Hash+1,Hash+tot,edge[i].y1)-Hash; x2=lower_bound(Hash+1,Hash+tot,edge[i].x2)-Hash; y2=lower_bound(Hash+1,Hash+tot,edge[i].y2)-Hash; if(x1==x2) { c[tot1++]=node1{x1,y1,x2,y2}; } else { r[tot2].x=x1,r[tot2].y=y1,r[tot2++].type=0; r[tot2].x=x2,r[tot2].y=y2,r[tot2++].type=1; } } sort(c,c+tot1); sort(r,r+tot2); ll sum=0; int j=0; for(int i=0;i<tot1;i++) { while(j<tot2&&(r[j].x<c[i].x1||(r[j].x==c[i].x1&&r[j].type==0)))//遍历在其左边的点(如果右端点等于直线的x,不减) { if(r[j].type==0) bit_add(r[j].y,1,tot+5); else bit_add(r[j].y,-1,tot+5); j++; } sum+=bit_getsum(c[i].y2)-bit_getsum(c[i].y1-1);//在直线的范围内的点才有效 } printf("%lld ",sum); } }
以上是关于树状数组+离散化的主要内容,如果未能解决你的问题,请参考以下文章