Hdu 4052 Adding New Machine(给你W*H大小的矩形,其中有N个地区不能使用(给出了这个地区的两个顶点的坐标即(x1,y1)和(x2,y2)),问能下多少个1*M的矩形)
2016-09-09 19:14
531 查看
传送门:Hdu 4052 Adding New Machine
题意:给你W*H大小的矩形,其中有N个地区不能使用(给出了这个地区的两个顶点的坐标即(x1,y1)和(x2,y2)),问能下多少个1*M的矩形。
思路:
因为放的新的矩形的面积是特殊的,所以我们只要先考虑行(列同理)
统计行的时候问题转化为找出多少个这样的方块(i,j),使得(i,j),(i,j+1)…(i,j+m-1)
->(x1-m+1,y1)到(x2,y2)之间的方块全都是不满足的,去掉不满足的之后剩下的全都是满足的(M=1特殊考虑)
原来的方块坐标和线段左边是不等价的,将(x1,y1)->(x1-1,y1-1)
题意:给你W*H大小的矩形,其中有N个地区不能使用(给出了这个地区的两个顶点的坐标即(x1,y1)和(x2,y2)),问能下多少个1*M的矩形。
思路:
因为放的新的矩形的面积是特殊的,所以我们只要先考虑行(列同理)
统计行的时候问题转化为找出多少个这样的方块(i,j),使得(i,j),(i,j+1)…(i,j+m-1)
->(x1-m+1,y1)到(x2,y2)之间的方块全都是不满足的,去掉不满足的之后剩下的全都是满足的(M=1特殊考虑)
原来的方块坐标和线段左边是不等价的,将(x1,y1)->(x1-1,y1-1)
#include<bits/stdc++.h> using namespace std; const int N=1e5+100; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 struct Point{ int x1,y1,x2,y2; }b ; int X[N*2],sumv[N*8]; int mark[N*8],L,R;//记录某个区间的下底边个数 //以横坐标作为线段(区间),对横坐标线段进行扫描 //扫描的作用是每次更新下底边总长度和下底边个数,增加新面积 struct node{ int l,r,h; int d; bool operator <(const node& rhs) const{ return h<rhs.h; } }a[N*2]; int search(double num,int l,int r){ while(l<=r){ int mid=(l+r)>>1; if(X[mid]==num) return mid; if(X[mid]<num) l=mid+1; else r=mid-1; } return -1; } void pushup(int rt,int l,int r){ if(mark[rt]) //表示该区间整个线段长度可以作为底边 sumv[rt]=X[r+1]-X[l]; else if(l==r)//叶子结点则底边长度为0(区间内线段长度为0) sumv[rt]=0; else sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1]; } void update(int l,int r,int rt,int d){ if(L<=l&&R>=r){//该区间是当前扫描线段的一部分,则该区间下底边总长以及上下底边个数差更新 mark[rt]+=d;//更新底边相差差个数 pushup(rt,l,r);//更新底边长 return ; } int mid=(l+r)>>1; if(L<=mid) update(lson,d); if(R>mid) update(rson,d); pushup(rt,l,r); } int M,W,H; long long ans; void solve(int n){ for(int i=1;i<=n;i++){ a[i*2-1]=node{max(b[i].x1-M+1,0),b[i].x2,b[i].y1,1},a[i*2]=node{max(b[i].x1-M+1,0),b[i].x2,b[i].y2,-1}; X[i*2-1]=max(b[i].x1-M+1,0),X[i*2]=b[i].x2; } ++n; a[n*2-1]=node{max(W-M+1,0),W,0,1},a[n*2]=node{max(W-M+1,0),W,H,-1}; X[n*2-1]=max(W-M+1,0),X[n*2]=W; sort(a+1,a+2*n+1); sort(X+1,X+2*n+1); int m=unique(X+1,X+2*n+1)-X;//去重 memset(mark,0,sizeof(mark)); memset(sumv,0,sizeof(sumv)); for(int i=1;i<2*n;i++){ L=search(a[i].l,1,m),R=search(a[i].r,1,m)-1; if(L<=R){ update(1,m,1,a[i].d); ans=ans+1LL*sumv[1]*(a[i+1].h-a[i].h); } } } int main(){ int n; while(scanf("%d%d%d%d",&W,&H,&n,&M)!=EOF){ for(int i=1;i<=n;i++){ scanf("%d%d%d%d",&b[i].x1,&b[i].y1,&b[i].x2,&b[i].y2); b[i].x1--,b[i].y1--; } ans=0; solve(n); if(M==1) printf("%lld\n",1LL*W*H-ans); else{ swap(W,H); for(int i=1;i<=n;i++) swap(b[i].x1,b[i].y1),swap(b[i].x2,b[i].y2); solve(n); printf("%lld\n",1LL*2*W*H-ans); } } return 0; }
相关文章推荐
- 二货小易有一个W*H的网格盒子,网格的行编号为0~H-1,网格的列编号为0~W-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。 对于两个格子坐标(x1,y1),(x2,y2)的欧几里得距离为: ( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) 的算术平方根 小易想知道最多可以放多少块蛋糕在网格盒子里。 输入描述: 每组数组包含网格长宽W,
- 二货小易有一个W*H的网格盒子,网格的行编号为0~H-1,网格的列编号为0~W-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。 对于两个格子坐标(x1,y1),(x2,y2)的
- 编程题-----三个顶点的坐标(x1,y1),(x2,y2),(x3,y3)什么方法求三角形的面积最简单
- 已知三角形三个顶点的坐标a(x1,y1),b(x2,y2),c(x3,y3)求三角形中心点即内接圆的圆心
- HDU 4052 Adding New Machine(矩形面积并)
- 输入两个坐标(x1,y1),(x2,y2),计算并输出两点间的距离
- hdu 4052 Adding New Machine 扫描线求矩形面积并
- hdu-4052/ LA 5694-Adding New Machine(线段树矩形面积并)
- HDU 4052 Adding New Machine(矩形面积并)
- 输入两个坐标(x1,y1),(x2,y2),计算并输出两点间的距离
- HDU 4052 Adding New Machine(矩形面积并)
- HDU 4052 Adding New Machine (线段树+离散化)
- hdu 4052 Adding New Machine(线段树+扫描线)
- 360oj 输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离。
- C/C++—— 输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离
- 两个向量(x1, y1), (x2, y2) 之间的平行四边形面积为啥是 (x1*y2-x2*y1)?
- 用c语言编写:输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离。
- 关于解决这个问题:从一个点(x,y)绕另一个点(x0,y0)旋转任意角度A后得到的坐标(x1,y1)的坐标是多少?
- Bestcoder Pro.ID 2001 输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离。
- 输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离。