用线段树求解坐标矩阵中的交并集面积思路及其模板代码
请客官老爷移步:
http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html
http://blog.csdn.net/qq_18661257/article/details/47658191
嘻嘻, 大奔 的思路 ;
代码简洁 用的是 区间更新; 而且可以一起求 矩阵的并 与交
两道模板题应用:
一道求交集,一道求并集;
HDU 1264 并集
HDU 1255 交集
【模板代码】:
#define lson rt << 1, l, mid #define rson rt << 1|1, mid + 1, r const int MAXN=2000+5; int col[MAXN<<2],n,cnt,res; double X[MAXN<<2],Sum[MAXN<<2],Sum2[MAXN<<2]; struct Seg{ double l,r,h; int flag; Seg(){} Seg(double l,double r,double h,int flag):l(l),r(r),h(h),flag(flag){} bool operator <(const Seg & object ) const{ return h<object.h; } }S[MAXN<<2]; void pushup(int rt,int l,int r) { if(col[rt])//覆盖一次 Sum[rt]=X[r+1]-X[l]; else if(l==r) Sum[rt]=0; else Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1]; if(col[rt]>=2)// 覆盖两次以上 Sum2[rt]=X[r+1]-X[l]; else if(l==r) Sum2[rt]=0; else if(col[rt]==1) Sum2[rt]=Sum[rt<<1] +Sum[rt<<1|1]; else if(col[rt]==0) Sum2[rt]=Sum2[rt<<1] +Sum2[rt<<1|1]; } void update(int L,int R,int c,int rt,int l,int r)// l,r 固定长度 L,R 变化长度 { if(L<=l&&r<=R) { col[rt]+=c; pushup(rt,l,r); return; } int mid=(l+r)>>1; if(L<=mid) update(L,R,c,lson); if(R>mid) update(L,R,c,rson); pushup(rt,l,r); } int binary_find(double x) { int lb=-1,ub=res-1; while(ub-lb>1) { int mid=(lb+ub)>>1; if(X[mid]>=x)ub=mid; else lb=mid; } return ub; } double solve(int n) { cnt=res=0; for(int i=0;i<n;i++) { double a,b,c,d; scanf("%lf %lf %lf %lf",&a,&b,&c,&d); S[cnt]=Seg(a,c,b,1); X[cnt++]=a; S[cnt]=Seg(a,c,d,-1); X[cnt++]=c; } sort(X,X+cnt); sort(S,S+cnt); res++; for(int i=1;i<cnt;i++){// 去重 if(X[i]!=X[i-1]) X[res++]=X[i]; } memset(Sum,0,sizeof(Sum)); memset(col,0,sizeof(col)); memset(Sum2,0,sizeof(Sum2)); double ans=0; for(int i=0;i<cnt-1;i++) { int l=binary_find(S[i].l);//二分左端点, int r=binary_find(S[i].r)-1; // 左闭右开 二分右端点 update(l,r,S[i].flag,1,0,res-1); ans+= Sum[1]*(S[i+1].h-S[i].h);// 矩阵并 //ans+= Sum2[1]*(S[i+1].h-S[i].h); //矩阵 交集 } return ans; }
123
岂曰无衣?与子同袍。王于兴师,修我戈矛。与子同仇!
岂曰无衣?与子同泽。王于兴师,修我矛戟。与子偕作!
岂曰无衣?与子同裳。王于兴师,修我甲兵。与子偕行!