http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3540
想到将旧机器向x或y方向扩展(m-1)个单位就好办了 将查询线段转化为查询单点 两遍扫描线求矩形面积并就好了
一开始没想到把问题转化 用区间合并正面求的 一直WA 还没调出来。。
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct node0
{
int x1,y1,x2,y2;
};
struct node1
{
int l,r;
};
struct node2
{
int l,r,h,f;
};
struct node3
{
int sum,val,leaf,f;
};
node0 ret[maxn];
node1 pre[4*maxn];
node2 seg[2*maxn];
node3 tree[16*maxn];
int gou[2*maxn];
int w,h,n,tot,mm,len;
bool cmpI(node1 n1,node1 n2)
{
return n1.l<n2.l;
}
bool cmpII(node2 n1,node2 n2)
{
return n1.h<n2.h;
}
void build(int l,int r,int cur)
{
int m;
tree[cur].sum=pre[r].r-pre[l].l+1;
tree[cur].val=0;
tree[cur].leaf=0,tree[cur].f=0;
if(l==r){
tree[cur].leaf=1;
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
}
int getpos(int tp,int pos)
{
int l,r,m;
if(!tp){
l=1,r=len;
while(l<=r){
m=(l+r)/2;
if(pre[m].l<pos) l=m+1;
else if(pre[m].l==pos) return m;
else r=m-1;
}
}
else{
l=1,r=len;
while(l<=r){
m=(l+r)/2;
if(pre[m].r<pos) l=m+1;
else if(pre[m].r==pos) return m;
else r=m-1;
}
}
}
void pushup(int cur)
{
if(tree[cur].f>0) tree[cur].val=tree[cur].sum;
else{
if(tree[cur].leaf) tree[cur].val=0;
else tree[cur].val=tree[2*cur].val+tree[2*cur+1].val;
}
}
void update(int pl,int pr,int f,int l,int r,int cur)
{
int m;
if(pl<=l&&r<=pr)
{
tree[cur].f+=f;
pushup(cur);
return;
}
m=(l+r)/2;
if(pl<=m) update(pl,pr,f,l,m,2*cur);
if(pr>m) update(pl,pr,f,m+1,r,2*cur+1);
pushup(cur);
}
ll solve()
{
ll res;
int i,j,x1,y1,x2,y2;
for(i=1;i<=n;i++){
x1=max(ret[i].x1-(mm-1),1),y1=ret[i].y1;
x2=ret[i].x2,y2=ret[i].y2;
seg[2*i-1].l=x1,seg[2*i-1].r=x2,seg[2*i-1].h=y1,seg[2*i-1].f=1;
seg[2*i].l=x1,seg[2*i].r=x2,seg[2*i].h=y2+1,seg[2*i].f=-1;
gou[2*i-1]=x1,gou[2*i]=x2;
}
tot=2*n;
if(mm>1){
x1=max(w-(mm-2),1),y1=1;
x2=w,y2=h;
tot+=2;
seg[tot-1].l=x1,seg[tot-1].r=x2,seg[tot-1].h=y1,seg[tot-1].f=1;
seg[tot].l=x1,seg[tot].r=x2,seg[tot].h=y2+1,seg[tot].f=-1;
gou[tot-1]=x1,gou[tot]=x2;
}
sort(seg+1,seg+tot+1,cmpII);
len=tot;
gou[++len]=1,gou[++len]=w;
sort(gou+1,gou+len+1);
len=unique(gou+1,gou+len+1)-gou-1;
j=0;
for(i=1;i<=len;i++){
j++;
pre[j].l=gou[i],pre[j].r=gou[i];
}
for(i=1;i+1<=len;i++){
if(gou[i]+1<=gou[i+1]-1){
j++;
pre[j].l=gou[i]+1,pre[j].r=gou[i+1]-1;
}
}
len=j;
sort(pre+1,pre+len+1,cmpI);
build(1,len,1);
res=(ll)(w)*(ll)(h);
for(i=1;i<=tot;i++){
res-=(ll)(seg[i].h-seg[i-1].h)*(ll)(tree[1].val);
seg[i].l=getpos(0,seg[i].l),seg[i].r=getpos(1,seg[i].r);
update(seg[i].l,seg[i].r,seg[i].f,1,len,1);
}
return res;
}
int main()
{
ll ans;
int i;
while(scanf("%d%d%d%d",&w,&h,&n,&mm)!=EOF){
for(i=1;i<=n;i++) scanf("%d%d%d%d",&ret[i].x1,&ret[i].y1,&ret[i].x2,&ret[i].y2);
ans=solve();
if(mm>1){
swap(w,h);
for(i=1;i<=n;i++) swap(ret[i].x1,ret[i].y1),swap(ret[i].x2,ret[i].y2);
ans+=solve();
}
printf("%lld\n",ans);
}
return 0;
}
/*
4 4 3 1
1 1 2 2
3 3 3 3
4 4 4 4
5 5 2 2
2 3 2 3
3 3 3 3
5 5 7 2
1 1 1 1
4 1 5 1
2 2 2 2
3 3 3 3
1 4 1 4
3 4 3 4
5 5 5 5
*/