UVALive 5694 Adding New Machine
来源:互联网 发布:毁三观 知乎 编辑:程序博客网 时间:2024/05/09 00:58
线段树扫描线。
题意: 在一个n*m平面内,有一些不重叠的矩形(可能退化成点或线),现在让你把一根给定长度的线竖直或水平地放进平面,要求不与任何原来存在的矩形重合,问有多少种放法。
解法: 在一根长度为a的线段上放置一根长度为b的线段共有a-b+1种放法。那么将给定的矩形拆成两根线段,用扫描线横着扫一次,竖着扫一次,就可以得到答案。有区间合并的过程。范围较大需要离散化。
本人在拆矩形时因为拆的是闭区间,一个矩形8条线,再因为线段树的4倍空间需求和维护变量的4倍空间需求,总共有5W个矩形,在ZOJ上内存堪堪卡过去。
注意一下计算时的讨论,还有长度为1的情况,见代码,不赘述。
#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define REP(i,a,b) for(int i=(a); i<(b); i++)#define clr(a,b) memset(a,b,sizeof(a))typedef long long lld;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define ls (rt<<1)#define rs (rt<<1|1)const int MAXN = 400010;int w,h,n,len;int san[MAXN],st;struct point { int x[2],y[2];}sp[MAXN];struct Seg { int l,r,h,s; Seg(){} Seg(int l, int r, int h, int s) : l(l), r(r), h(h), s(s) {} bool operator < (const Seg &tt) const { if(h == tt.h) return s > tt.s; return h < tt.h; }}ss[MAXN<<2];int tot;lld ans;int lpa[MAXN<<2],rpa[MAXN<<2],sum[MAXN<<2],cnt[MAXN<<2];int Count(int x) { return x < len ? 0 : x-len+1;}void up(int l, int r, int rt) { int m = l+r>>1; sum[rt] = sum[ls] + sum[rs]; lpa[rt] = lpa[ls]; if(lpa[rt] == m-l+1) lpa[rt] += lpa[rs]; rpa[rt] = rpa[rs]; if(rpa[rt] == r-m) rpa[rt] += rpa[ls]; sum[rt] -= Count(san[m]-san[m-rpa[ls]+1]+1); sum[rt] -= Count(san[m+lpa[rs]]-san[m+1]+1); sum[rt] += Count(san[m+lpa[rs]]-san[m-rpa[ls]+1]+1);}void build(int l, int r, int rt) { sum[rt] = Count(san[r]-san[l]+1); lpa[rt] = rpa[rt] = r-l+1; cnt[rt] = 0; if(l == r) return ; int m = l+r>>1; build(lson); build(rson);}void update(int L, int R, int x, int l, int r, int rt) { if(L<=l && r<=R) { cnt[rt] += x; if(cnt[rt] == 0) { lpa[rt] = rpa[rt] = r - l + 1; sum[rt] = Count(san[r]-san[l]+1); } else { rpa[rt] = lpa[rt] = 0; sum[rt] = 0; } return ; } else { int m = l+r>>1; if(L<=m) update(L,R,x,lson); if(m< R) update(L,R,x,rson); up(l,r,rt); }}void gaox() { if(n == 0) { ans += (lld)Count(w) * h; return ; } if(w < len) return ; tot = 0; REP(i,0,n) { ss[tot++] = Seg(sp[i].x[0],sp[i].x[1],sp[i].y[0],1); ss[tot++] = Seg(sp[i].x[0],sp[i].x[1],sp[i].y[1],-1); } sort(ss,ss+tot); int l = lower_bound(san,san+st,1) - san; int r = lower_bound(san,san+st,w) - san; build(l,r,1); REP(i,0,tot-1) { int L = lower_bound(san,san+st,ss[i].l) - san; int R = lower_bound(san,san+st,ss[i].r) - san; if(ss[i].s < 0 && (ss[i-1].h != ss[i].h || ss[i-1].s != ss[i].s)) ans += sum[1]; update(L,R,ss[i].s,l,r,1); if(ss[i].s < 0 && ss[i+1].h != ss[i].h) ans += (lld)sum[1] * (ss[i+1].h - ss[i].h - 1); else if(ss[i].s > 0) ans += (lld)sum[1] * (ss[i+1].h - ss[i].h); } if(ss[tot-1].s != ss[tot-2].s || ss[tot-1].h != ss[tot-2].h) ans += sum[1]; ans += (lld)Count(w) * (ss[0].h-1 + h-ss[tot-1].h);}void gaoy() { if(n == 0) { ans += (lld)Count(h) * w; return ; } if(h < len) return ; tot = 0; REP(i,0,n) { ss[tot++] = Seg(sp[i].y[0],sp[i].y[1],sp[i].x[0],1); ss[tot++] = Seg(sp[i].y[0],sp[i].y[1],sp[i].x[1],-1); } sort(ss,ss+tot); int l = lower_bound(san,san+st,1) - san; int r = lower_bound(san,san+st,h) - san; build(l,r,1); REP(i,0,tot-1) { int L = lower_bound(san,san+st,ss[i].l) - san; int R = lower_bound(san,san+st,ss[i].r) - san; int temp; if(ss[i].s < 0 && (ss[i-1].h != ss[i].h || ss[i-1].s != ss[i].s)) ans += sum[1]; update(L,R,ss[i].s,l,r,1); if(ss[i].s < 0 && ss[i+1].h != ss[i].h) ans += (lld)sum[1] * (ss[i+1].h - ss[i].h - 1); else if(ss[i].s > 0) ans += (lld)sum[1] * (ss[i+1].h - ss[i].h); } if(ss[tot-1].s != ss[tot-2].s || ss[tot-1].h != ss[tot-2].h) ans += sum[1]; ans += (lld)Count(h) * (ss[0].h-1 + w-ss[tot-1].h);}int main() { while(~scanf("%d%d%d%d", &w, &h, &n, &len)) { st = 0; ans = 0; san[st++] = 1; san[st++] = w; san[st++] = h; REP(i,0,n) { REP(j,0,2) { scanf("%d%d", &sp[i].x[j],&sp[i].y[j]); san[st++] = sp[i].x[j]; san[st++] = sp[i].y[j]; } san[st++] = sp[i].x[0]-1; san[st++] = sp[i].x[1]+1; san[st++] = sp[i].y[0]-1; san[st++] = sp[i].y[1]+1; } sort(san,san+st); st = unique(san,san+st) - san; gaox(); if(len != 1) gaoy(); printf("%lld\n", ans); } return 0;}/*4 4 3 23 2 3 22 3 2 33 3 4 4ans = 10*/
- UVALive 5694 Adding New Machine
- zoj 3540 Adding New Machine
- hdu 4052 Adding New Machine
- hdu4052-Adding New Machine-题解
- [线段树]HDU 4052 Adding New Machine
- UVA 1492 - Adding New Machine(线段树)
- uva 1492 - Adding New Machine(线段树)
- hdu 4052 Adding New Machine,set
- UVA1492 - Adding New Machine(扫描线)
- hdu-4052/ LA 5694-Adding New Machine(线段树矩形面积并)
- zoj 3540 Adding New Machine(map+离散化)
- hdu 4052 Adding New Machine(线段树+扫描线)
- HDU 4052 Adding New Machine(矩形面积并)
- HDU 4052 Adding New Machine (线段树)
- 【HDU4052】【ZOJ3540】Adding New Machine 线段树+扫描线
- Adding a new disk to a VMWare Virtual Machine in Linux
- 在VMWare 中增加磁盘(Adding a new disk to a VMware Virtual Machine in Linux)
- hdu 4052 Adding New Machine 扫描线求矩形面积并
- php xml xpath 很好用
- poj 1466
- vs2005-vs2010中编译log4cxx-0.10.0的详细方法
- 依赖注入的方式有哪些?
- 在windows7下删除ubuntu
- UVALive 5694 Adding New Machine
- Arduino 控制四路继电器
- WKT简介
- Linux学习笔记:解决因 /boot 分区空间不足导致的卸载旧内核失败
- 共用体的定义和应用【C++】
- js中onload与onunload妙用(转载)
- 我对广播的理解:手动进行广播组件的注册
- 在Spring配置JNDI
- 常见Java面试题 – 第二部分:equals与==