我们考虑 每个新机器往右放的起始点(1*1的块)
那么我们只要求出哪些位置不可以放就可以了,比如说 3*3 的矩阵 新机器长为2 旧机器在2 2 那么 1 1这个点就不可以放新机器(考虑机器往右放的起始点)
再考虑右边界,右边界左边m-1个位置也不可以放
再考虑往下放的起始点,同理了
综上我们只要分别求出 哪些点不可以放 再用所有点减去就可以了
其实这就转化成了求矩形面积合并的问题了
注意特判m=1 横着放竖着放重复计算了
线段树实现矩形面积合并时还是要注意一些细节,每个节点储存的是这个点到右边那个点的距离
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
ll w,h,n,m;
struct data
{
ll x1,x2,y;
int flag;
} a[maxn<<2],b[maxn<<2];
ll hasha[maxn],hashb[maxn];
ll sum[maxn<<2];
ll col[maxn<<2],flaga[maxn],flagb[maxn];
inline bool cmp(data a,data b)
{
return a.y<b.y;
}
void pushup(ll s,ll l,ll r)
{
if(col[s]) sum[s]=hasha[r+1]-hasha[l];
else if(l==r) sum[s]=0;
else
{
sum[s]=sum[s*2]+sum[s*2+1];
}
}
void update(ll L,ll R,ll l,ll r,ll flag,ll s)
{
if(L<=l&&R>=r)
{
col[s]+=flag;
pushup(s,l,r);
return ;
}
ll m=(l+r)/2;
if(L<=m)
{
update(L,R,l,m,flag,s*2);
}
if(R>m)
{
update(L,R,m+1,r,flag,s*2+1);
}
pushup(s,l,r);
}
int main()
{
while(~scanf("%lld%lld%lld%lld",&w,&h,&n,&m))
{
for(int i = 1; i <= n; ++i)
{
ll xx1,yy1,xx2,yy2;
scanf("%lld%lld%lld%lld",&xx1,&yy1,&xx2,&yy2);
a[i*2].x1=a[i*2-1].x1=xx1-m+1>0?xx1-m+1:1;
a[i*2].x2=a[i*2-1].x2=xx2+1;
a[i*2-1].flag=1;
a[i*2].flag=-1;
hasha[i*2-1]=a[i*2-1].x1;
hasha[2*i]=a[i*2].x2;
a[i*2-1].y=yy1;
a[i*2].y=yy2+1;
b[i*2].x1=b[i*2-1].x1=yy1-m+1>0?yy1-m+1:1;
b[i*2].x2=b[i*2-1].x2=yy2+1;
b[i*2-1].y=xx1;
b[i*2].y=xx2+1;
hashb[i*2-1]=b[i*2-1].x1;
hashb[2*i]=b[i*2].x2;
b[i*2-1].flag=1;
b[i*2].flag=-1;
}
memset(col,0,sizeof col);
memset(sum,0,sizeof sum);
a[2*n+2].x1=a[2*n+1].x1=w-m+2>0?w-m+2:1;
a[2*n+1].flag=1;
a[2*n+2].flag=-1;
a[2*n+2].x2=a[2*n+1].x2=w+1;
a[2*n+1].y=1;
a[2*n+2].y=h+1;
hasha[2*n+1]=a[n*2+1].x1;
hasha[2*n+2]=a[n*2+2].x2;
sort(a+1,a+2*n+3,cmp);
sort(hasha+1,hasha+2*n+3);
ll sz=unique(hasha+1,hasha+2*n+3)-hasha;
long long ans=0;
for(ll i = 1; i <= 2*n+2; ++i)
{
ll l=lower_bound(hasha+1,hasha+sz,a[i].x1)-hasha;
ll r=lower_bound(hasha+1,hasha+sz,a[i].x2)-hasha-1;
if(r>=l) update(l,r,1,sz-1,a[i].flag,1);
ans+=sum[1]*(a[i+1].y-a[i].y);
}
for(ll i = 1; i <= 2*n+2; ++i)
{
hasha[i]=hashb[i];
a[i]=b[i];
}
a[2*n+2].x1=a[2*n+1].x1=h-m+2>0?h-m+2:1;
a[2*n+2].x2=a[2*n+1].x2=h+1;
a[2*n+1].y=1;
a[2*n+2].y=w+1;
a[2*n+1].flag=1;
a[2*n+2].flag=-1;
hasha[2*n+1]=a[n*2+1].x1;
hasha[2*n+2]=a[n*2+2].x2;
memset(col,0,sizeof col);
memset(sum,0,sizeof sum);
sort(a+1,a+2*n+3,cmp);
sort(hasha+1,hasha+2*n+3);
sz=unique(hasha+1,hasha+2*n+3)-hasha;
for(int i = 1; i <= 2*n+2; ++i)
{
ll l=lower_bound(hasha+1,hasha+sz,a[i].x1)-hasha;
ll r=lower_bound(hasha+1,hasha+sz,a[i].x2)-hasha-1;
if(r>=l) update(l,r,1,sz-1,a[i].flag,1);
ans+=sum[1]*(a[i+1].y-a[i].y);
}
ans=(long long)w*h*2-ans;
if(m==1) ans/=2;
cout<<ans<<endl;
}
return 0;
}