题目大意:给一个w*h的矩阵,给n个矩形,n个矩阵互不相交。再给一个1*m的矩形,要求与给定的n个矩形不相交,求能摆放的方案种数。
题目分析:w和h很大,n有50000,所以离散化+线段树。因为要摆放的矩形是1*m的,所以这个矩形只有2种姿势:横着or竖着。所以从左向右扫描一遍,求出空地的面积并,从上向下扫描一遍,求剩余面积并相加即可。不过要对之前的n个矩形处理一下:对于第i个矩形,从左向右扫描的话,将此矩形的右界向右伸长m-1,因为从左向右是恒着扫描的,如果1*m的矩形要横着放,那么矩形i的右界的右边m-1个格子显然也是不能放的,竖直方向也是同理,下界向下伸长m-1,直到越界为止。一开始的话,大矩形左到右和上到下1~m-1这个范围赋值一个很大的数,因为无论何时,这段都是不能放矩形的。大矩形的左右界,上下界也作为一条扫描线方便些。
trick:当m为1的时候,水平竖直放都一样,所以求出来的答案除2!
ps:比赛的时候以为是dp,竟然没看出是道线段树,简直弱爆了。。。
pps:用线段树写个矩形面积并写了一天,简直弱爆了。。。
ppps:zoj竟然用不了__int64,太ws了,累觉不爱了。。。
详情请见代码:
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 500005;
int hx[N + N],hy[N + N],nx,ny;
struct node
{
int a,b,c,d;
}linex[N],liney[N];
int w,h,n,m;
int cmp(struct node a,struct node b)
{
return a.a < b.a;
}
struct nd
{
int len,cover;
};
struct sgt
{
struct nd tree[N<<2];
void init(int num,int s,int e)
{
tree[num].cover = tree[num].len = 0;
if(s == e)
return;
int mid = (s + e)>>1;
init(num<<1,s,mid);
init(num<<1|1,mid + 1,e);
}
void insert(int num,int s,int e,int l,int r,int val,int dir)
{
if(s == e)
{
tree[num].cover += val;
if(tree[num].cover)
{
if(dir)
tree[num].len = hx[e + 1] - hx[s];
else
tree[num].len = hy[e + 1] - hy[s];
}
else
tree[num].len = 0;
return;
}
if(s == l && e == r)
{
if(tree[num].cover > 0 || val > 0)//少了val>0会T.....
{
tree[num].cover += val;
if(tree[num].cover > 0)
{
if(dir)
tree[num].len = hx[e + 1] - hx[s];
else
tree[num].len = hy[e + 1] - hy[s];
}
else
tree[num].len = tree[num<<1].len + tree[num<<1|1].len;
return;
}
}
int mid = (s + e)>>1;
if(tree[num].cover)
{
tree[num<<1].cover += tree[num].cover;
tree[num<<1|1].cover += tree[num].cover;
if(dir)//再往下更新一层!!!
{
tree[num<<1].len = hx[mid + 1] - hx[s];
tree[num<<1|1].len = hx[e + 1] - hx[mid + 1];
}
else
{
tree[num<<1].len = hy[mid + 1] - hy[s];
tree[num<<1|1].len = hy[e + 1] - hy[mid + 1];
}
tree[num].cover = 0;
}
if(r <= mid)
insert(num<<1,s,mid,l,r,val,dir);
else
{
if(l > mid)
insert(num<<1|1,mid + 1,e,l,r,val,dir);
else
{
insert(num<<1,s,mid,l,mid,val,dir);
insert(num<<1|1,mid + 1,e,mid + 1,r,val,dir);
}
}
tree[num].len = tree[num<<1].len + tree[num<<1|1].len;
}
}stx,sty;
int getx(int x)
{
int l,r,mid;
l = 1;r = nx;
while(l <= r)
{
mid = (l + r)>>1;
if(hx[mid] == x)
return mid;
else
{
if(hx[mid] > x)
r = mid - 1;
else
l = mid + 1;
}
}
}
int gety(int x)
{
int l,r,mid;
l = 1;r = ny;
while(l <= r)
{
mid = (l + r)>>1;
if(hy[mid] == x)
return mid;
else
{
if(hy[mid] > x)
r = mid - 1;
else
l = mid + 1;
}
}
}
int main()
{
int i,j;
int x1,x2,y1,y2;
while(scanf("%d",&w) != EOF)
{
scanf("%d%d%d",&h,&n,&m);
w ++;h ++;
nx = ny = 1;
linex[1].a = liney[1].a = 1;
linex[1].b = liney[1].b = m;
linex[1].c = h;liney[1].c = w;
for(i = 2;i <= n + n;i += 2)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x2 ++;y2 ++;
linex[i].a = x1;linex[i].b = y1;linex[i].c = y2 + m - 1;linex[i].d = 1;
if(linex[i].c > h)
linex[i].c = h;
linex[i + 1].a = x2;linex[i + 1].b = y1;linex[i + 1].c = y2 + m - 1;linex[i + 1].d = -1;
if(linex[i + 1].c > h)
linex[i + 1].c = h;
liney[i].a = y1;liney[i].b = x1;liney[i].c = x2 + m - 1;liney[i].d = 1;
if(liney[i].c > w)
liney[i].c = w;
liney[i + 1].a = y2;liney[i + 1].b = x1;liney[i + 1].c = x2 + m - 1;liney[i + 1].d = -1;
if(liney[i + 1].c > w)
liney[i + 1].c = w;
hx[nx ++] = x1;hx[nx ++] = x2;hx[nx ++] = liney[i].c;
hy[ny ++] = y1;hy[ny ++] = y2;hy[ny ++] = linex[i].c;
}
linex[i].a = w;liney[i].a = h;
linex[i].b = liney[i].b = m;
linex[i].c = h;
liney[i].c = w;
hx[nx ++] = 1;hx[nx ++] = w;hx[nx ++] = m;
hy[ny ++] = 1;hy[ny ++] = h;hy[ny ++] = m;
sort(linex + 1,linex + n + n + 3,cmp);
sort(liney + 1,liney + n + n + 3,cmp);
sort(hx + 1,hx + nx);
sort(hy + 1,hy + ny);
j = nx;
nx = ny = 2;
for(i = 2;i < j;i ++)
{
if(hx[i] != hx[i - 1])
hx[nx ++] = hx[i];
if(hy[i] != hy[i - 1])
hy[ny ++] = hy[i];
}
nx --;ny --;
stx.init(1,1,ny);
sty.init(1,1,nx);
int l,r;
l = 1;r = gety(m) - 1;
if(l <= r)
stx.insert(1,1,ny,l,r,1000000,0);
r = getx(m) - 1;
if(l <= r)
sty.insert(1,1,nx,l,r,1000000,1);
__int64 ans = 0;
for(i = 2;i <= n + n + 2;i ++)
{
ans += (__int64)(linex[i].a - linex[i - 1].a) * (h - 1 - stx.tree[1].len);
ans += (__int64)(liney[i].a - liney[i - 1].a) * (w - 1 - sty.tree[1].len);
l = gety(linex[i].b);r = gety(linex[i].c) - 1;
stx.insert(1,1,ny,l,r,linex[i].d,0);
l = getx(liney[i].b);r = getx(liney[i].c) - 1;
sty.insert(1,1,nx,l,r,liney[i].d,1);
}
if(m == 1)
ans /= 2;
printf("%I64d\n",ans);
}
return 0;
}
/*
3 3 1 2
2 2 2 2
3 3 1 3
2 2 2 2
2 3 2 2
1 1 1 1
2 3 2 3
3 3 0 2
3 3 0 1
3 3 1 1
2 2 2 2
5 4 1 2
2 2 3 3
5 4 5 2
1 1 1 2
2 3 2 4
3 1 3 2
4 3 4 4
5 1 5 2
4 4 2 2
2 1 3 2
2 3 3 4
*/
//1453MS 12812K