覆盖的面积 HDU - 1255 线段树+扫描线+离散化 求特定交叉面积
#include<cstdio> #include<map> #include<algorithm> using namespace std; const int N=101010; struct Node { double x,yl,yh; int w; bool operator<(Node t)const { return x<t.x; } }edge[N]; struct { int l,r,cover; }tr[N]; double ys[N]; void build(int u,int l,int r) { int mid=l+r>>1; tr[u].l=l,tr[u].r=r; tr[u].cover=0; if (r-l>1) { build(u<<1,l,mid); build(u<<1|1,mid,r); } } void modify(int u,int l,int r,int val) { int mid=tr[u].l+tr[u].r>>1; if(tr[u].l==l&&tr[u].r==r) { tr[u].cover+=val; } else if(tr[u].r-tr[u].l>1) { if (l>=mid) modify(u<<1|1,l,r,val); else if(r<=mid) modify(u<<1,l,r,val); else { modify(u<<1,l,mid,val); modify(u<<1|1,mid,r,val); } } } void query(int root,double &ans) { //如果被覆盖次数大于1 if (tr[root].cover>1) ans+=ys[tr[root].r]-ys[tr[root].l]; //上式不满足时,可能往下的子区间满足,就往下递归 //如果不是叶节点 else if(tr[root].r-tr[root].l>1) { tr[root<<1].cover+=tr[root].cover; tr[root<<1|1].cover+=tr[root].cover; tr[root].cover=0; query(root<<1,ans); query(root<<1|1,ans); } } int main() { int T,N; double x1,x2,y1,y2,ans,res; scanf("%d",&T); while(T--) { res=0; map<double,int>mp; scanf("%d",&N); for (int i=1,j=1;i<=N;++i,j+=2) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); //入边 edge[j].x=x1,edge[j].yl=y1,edge[j].yh=y2; edge[j].w=1; //出边 edge[j+1].x=x2,edge[j+1].yl=y1,edge[j+1].yh=y2; edge[j+1].w=-1; //扫描线 ys[j]=y1,ys[j+1]=y2; } //按x排序 sort(edge+1,edge+1+2*N); //y离散化 sort(ys+1,ys+1+2*N); int cnt=unique(ys+1,ys+1+2*N)-(ys+1); build(1,1,cnt); //离散化 //映射之后的编号 ,查询的实话再映射到ys中去 for (int i=1;i<=cnt;++i) mp[ys[i]]=i; for (int i=1;i<2*N;++i) { ans=0; //插进去 modify(1,mp[edge[i].yl],mp[edge[i].yh],edge[i].w); query(1,ans); res+=ans*(edge[i+1].x-edge[i].x); } printf("%.2lf\n",res); } return 0; }