用线段树求解坐标矩阵中的交并集面积思路及其模板代码

来源:互联网 发布:js判断哪个tr被双击 编辑:程序博客网 时间:2024/05/28 19:23


请客官老爷移步:

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, rconst 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

原创粉丝点击