hdu4052 Adding New Machine,set
比较老的题。给一个矩形和一些已经覆盖了的小矩形,问在剩余的空格上放一个长为m的条有多少种放法。
可以用线段树化为矩形面积并搞。这里练习一下平衡树的做法,set也比较短。
把矩形变为入和出两个事件,根据这些事件计算某行有多少空格,就能计算横着放有多少种放法。然后横竖各做一遍。
这里利用set可以找到插入线段的两端第一个非空位置。
注意几个地方:
1.long long
2.m为1的情况,横竖是一样的。
3.排序事件时,要先出后进。
比较老的题。给一个矩形和一些已经覆盖了的小矩形,问在剩余的空格上放一个长为m的条有多少种放法。
可以用线段树化为矩形面积并搞。这里练习一下平衡树的做法,set也比较短。
把矩形变为入和出两个事件,根据这些事件计算某行有多少空格,就能计算横着放有多少种放法。然后横竖各做一遍。
这里利用set可以找到插入线段的两端第一个非空位置。
注意几个地方:
1.long long
2.m为1的情况,横竖是一样的。
3.排序事件时,要先出后进。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
#define NN 50100
int m;
set<int> st;
struct rect{
int sx,sy,ex,ey;
}r[NN];
struct node{
int sx,ex,t,tag;
void init(int a,int b,int c,int d){
sx=a;ex=b;t=c;tag=d;
}
}ev[NN*2],nd;
bool cmp(node x,node y){
if (x.t==y.t) return x.tag<y.tag;
else return x.t<y.t;
}
int initeven1(int n,int w,int h){
int i;
int ret=0;
for(i=1;i<=n;++i){
nd.init(r[i].sy,r[i].ey,r[i].sx,1);
ev[++ret]=nd;
nd.init(r[i].sy,r[i].ey,r[i].ex+1,-1);
if (nd.t<=w) ev[++ret]=nd;
}
nd.init(0,h+1,1,1);
ev[0]=nd;
nd.init(0,h+1,w+1,-1);
ev[ret+1]=nd;
sort(ev+1,ev+ret+1,cmp);
return ret;
}
int initeven2(int n,int w,int h){
int i;
int ret=0;
for(i=1;i<=n;++i){
nd.init(r[i].sx,r[i].ex,r[i].sy,1);
ev[++ret]=nd;
nd.init(r[i].sx,r[i].ex,r[i].ey+1,-1);
if (nd.t<=w) ev[++ret]=nd;
}
nd.init(0,h+1,1,1);
ev[0]=nd;
nd.init(0,h+1,w+1,-1);
ev[ret+1]=nd;
sort(ev+1,ev+ret+1,cmp);
return ret;
}
int insert(node ev){
int ret=0;
set<int>::iterator it;
set<int>::iterator rit;
int ll,rr,tmp;
if (ev.tag<0){
it=st.find(ev.ex);
rit=st.find(ev.sx);
it++;
rit--;
ll=*rit;
rr=*it;
tmp=ev.sx-1-ll;
if (tmp>=m) ret-=tmp+1-m;
tmp=rr-1-ev.ex;
if (tmp>=m) ret-=tmp+1-m;
tmp=rr-1-ll;
if (tmp>=m) ret+=tmp+1-m;
st.erase(ev.sx);
st.erase(ev.ex);
}
else{
st.insert(ev.sx);
st.insert(ev.ex);
it=st.find(ev.ex);
rit=st.find(ev.sx);
it++;
rit--;
ll=*rit;
rr=*it;
tmp=ev.sx-1-ll;
if (tmp>=m) ret+=tmp+1-m;
tmp=rr-1-ev.ex;
if (tmp>=m) ret+=tmp+1-m;
tmp=rr-1-ll;
if (tmp>=m) ret-=tmp+1-m;
}
return ret;
}
long long work(int n,int tn,int w,int h){
int i;
int t,tlen;
long long sum=0,ret=0;
st.clear();
insert(ev[0]);
if (h>=m){
sum=h+1-m;
}
ret+=sum*(ev[1].t-1);
for(i=1;i<=tn;){
t=ev[i].t;
while(ev[i].t==t){
sum+=insert(ev[i]);
++i;
}
tlen=ev[i].t-t;
ret+=sum*tlen;
}
return ret;
}
int n,w,h;
int main(){
//freopen("bin.txt","r",stdin);
int i,tn;
long long ans1,ans2=0;
while(scanf("%d%d%d%d",&w,&h,&n,&m)!=EOF){
for(i=1;i<=n;++i){
scanf("%d%d%d%d",&r[i].sx,&r[i].sy,&r[i].ex,&r[i].ey);
}
tn=initeven1(n,w,h);
ans1=work(n,tn,w,h);
if (m>1){
tn=initeven2(n,h,w);
ans2=work(n,tn,h,w);
}
else ans2=0;
printf("%I64d\n",ans1+ans2);
}
return 0;
}