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*/


原创粉丝点击