传送门: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)
#include
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[N];
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 h2];
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]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;
}