求矩阵的面积并
采用的是区间更新
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #define lson rt<<1,L,mid #define rson rt<<1|1,mid+1,R /* AC 一开始一直WA的原因是,hashx写成了int型!!! 第一次用的是直接单点更新,这次用区间更新写写看 */ using namespace std; const int maxn=105; int n; double x1,y1,x2,y2; //题目中有误,题目说的是(x1,y1)为矩形的左上端点,(x2,y2)为矩形的右下端点, //但是给出的值y1<y2。。。也就是说(x1,y1)为矩形的左下端点,(x2,y2)为矩形的右上端点 double hashx[maxn<<1]; int idx; int mark[maxn<<1]; double sum[maxn<<1]; struct Line{ double y,l,r; int tp; bool operator<(const Line tmp)const{ return y<tmp.y; } }line[maxn<<2]; struct Node{ double sum; int mark; }tree[maxn<<4]; void build(int rt,int L,int R){ tree[rt].sum=tree[rt].mark=0; if(L==R){ return ; } int mid=(L+R)>>1; build(rt<<1,L,mid); build(rt<<1|1,mid+1,R); } void pushUp(int rt,int L,int R){ if(tree[rt].mark){ tree[rt].sum=hashx[R+1]-hashx[L]; } else{ if(L==R) tree[rt].sum=0; else tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } } void update(int rt,int L,int R,int l,int r,int val){ if(L==R){ //原本写了个tree[rt].mark。。。 tree[rt].mark+=val; pushUp(rt,L,R); return; } int mid=(L+R)>>1; if(r<=mid) update(lson,l,r,val); else if(l>mid) update(rson,l,r,val); else{ update(lson,l,mid,val); update(rson,mid+1,r,val); } pushUp(rt,L,R); } //二分搜索对应的映射,也可以用map建立double-int的映射关系 int binarySearch(double x){ int l=0,r=n+1,mid; //注意:l初试为0,r初试为n+1。否则若是1和n的话,若搜索的值为hashx[1]或者hashx[n]就错了。 while (r-l>1) //这里若为r>l的话,就会陷入死循环。举例:l=1,r=2,mid=1,x>=hashx[1]。 { mid=(l+r)>>1; if (hashx[mid]<=x) l=mid; else r=mid; } return l; } int main() { int a,b,t=0; while(scanf("%d",&n),n){ idx=0; t++; for(int i=1;i<=n;i++){ scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); line[2*i-1].y=y1;line[2*i-1].l=x1;line[2*i-1].r=x2;line[2*i-1].tp=1; line[2*i].y=y2;line[2*i].l=x1;line[2*i].r=x2;line[2*i].tp=-1; hashx[++idx]=x1; hashx[++idx]=x2; } n=n*2; build(1,1,n); sort(line+1,line+1+n); sort(hashx+1,hashx+idx+1); double ans=0; for(int i=1;i<=n;i++){ ans+=tree[1].sum*(line[i].y-line[i-1].y); a=binarySearch(line[i].l); b=binarySearch(line[i].r)-1; update(1,1,n,a,b,line[i].tp); } printf("Test case #%d ",t); printf("Total explored area: %.2lf ",ans); } return 0; }
采用的是单点更新
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> /* AC */ using namespace std; const int maxn=105; int n; double x1,y1,x2,y2; //题目中有误,题目说的是(x1,y1)为矩形的左上端点,(x2,y2)为矩形的右下端点, //但是给出的值y1<y2。。。也就是说(x1,y1)为矩形的左下端点,(x2,y2)为矩形的右上端点 double hashx[maxn<<1]; int idx; int mark[maxn<<1]; double sum[maxn<<1]; struct Line{ double y,l,r; int tp; bool operator<(const Line tmp)const{ return y<tmp.y; } }line[maxn<<2]; struct Node{ double sum; int mark; }tree[maxn<<4]; void build(int rt,int L,int R){ tree[rt].sum=tree[rt].mark=0; if(L==R){ return ; } int mid=(L+R)>>1; build(rt<<1,L,mid); build(rt<<1|1,mid+1,R); } void pushUp(int rt){ tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } void update(int rt,int x,int L,int R,int val){ if(L==R){ tree[L].mark+=val; //mark[x]+=val; if(tree[L].mark) tree[rt].sum=hashx[x+1]-hashx[x]; else tree[rt].sum=0; return; } int mid=(L+R)>>1; if(x<=mid) update(rt<<1,x,L,mid,val); else update(rt<<1|1,x,mid+1,R,val); pushUp(rt); } //二分搜索对应的映射,也可以用map建立double-int的映射关系 int binarySearch(double x){ int l=0,r=n+1,mid; //注意:l初试为0,r初试为n+1。否则若是1和n的话,若搜索的值为hashx[1]或者hashx[n]就错了。 while (r-l>1) //这里若为r>l的话,就会陷入死循环。举例:l=1,r=2,mid=1,x>=hashx[1]。 { mid=(l+r)>>1; if (hashx[mid]<=x) l=mid; else r=mid; } return l; } int main() { int a,b,t=0; while(scanf("%d",&n),n){ idx=0; t++; memset(mark,0,sizeof(mark)); for(int i=1;i<=n;i++){ scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); line[2*i-1].y=y1;line[2*i-1].l=x1;line[2*i-1].r=x2;line[2*i-1].tp=1; line[2*i].y=y2;line[2*i].l=x1;line[2*i].r=x2;line[2*i].tp=-1; hashx[++idx]=x1; hashx[++idx]=x2; } n=n*2; build(1,1,n); sort(line+1,line+1+n); sort(hashx+1,hashx+idx+1); double ans=0; for(int i=1;i<=n;i++){ ans+=tree[1].sum*(line[i].y-line[i-1].y); a=binarySearch(line[i].l); b=binarySearch(line[i].r)-1; for(int j=a;j<=b;j++) update(1,j,1,n,line[i].tp); } printf("Test case #%d ",t); printf("Total explored area: %.2lf ",ans); } return 0; }