题目请戳这里
题目大意:给一个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