您的位置:首页 > 其它

hdu 4052 Adding New Machine,set

2014-10-15 22:19 267 查看
hdu4052 Adding New Machine,set

比较老的题。给一个矩形和一些已经覆盖了的小矩形,问在剩余的空格上放一个长为m的条有多少种放法。

可以用线段树化为矩形面积并搞。这里练习一下平衡树的做法,set也比较短。

把矩形变为入和出两个事件,根据这些事件计算某行有多少空格,就能计算横着放有多少种放法。然后横竖各做一遍。

这里利用set可以找到插入线段的两端第一个非空位置。

注意几个地方:

1.long long

2.m为1的情况,横竖是一样的。

3.排序事件时,要先出后进。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
#define NN 50100

int m;
set<int> st;

struct rect{
    int sx,sy,ex,ey;
}r[NN];

struct node{
    int sx,ex,t,tag;
    void init(int a,int b,int c,int d){
        sx=a;ex=b;t=c;tag=d;
    }

}ev[NN*2],nd;

bool cmp(node x,node y){
    if (x.t==y.t) return x.tag<y.tag;
    else return x.t<y.t;
}

int initeven1(int n,int w,int h){
    int i;
    int ret=0;
    for(i=1;i<=n;++i){
        nd.init(r[i].sy,r[i].ey,r[i].sx,1);
        ev[++ret]=nd;
        nd.init(r[i].sy,r[i].ey,r[i].ex+1,-1);
        if (nd.t<=w) ev[++ret]=nd;
    }
    nd.init(0,h+1,1,1);
    ev[0]=nd;
    nd.init(0,h+1,w+1,-1);
    ev[ret+1]=nd;
    sort(ev+1,ev+ret+1,cmp);
    return ret;
}

int initeven2(int n,int w,int h){
    int i;
    int ret=0;
    for(i=1;i<=n;++i){
        nd.init(r[i].sx,r[i].ex,r[i].sy,1);
        ev[++ret]=nd;
        nd.init(r[i].sx,r[i].ex,r[i].ey+1,-1);
        if (nd.t<=w) ev[++ret]=nd;
    }
    nd.init(0,h+1,1,1);
    ev[0]=nd;
    nd.init(0,h+1,w+1,-1);
    ev[ret+1]=nd;
    sort(ev+1,ev+ret+1,cmp);
    return ret;
}

int insert(node ev){
    int ret=0;
    set<int>::iterator it;
    set<int>::iterator rit;
    int ll,rr,tmp;
    if (ev.tag<0){
        it=st.find(ev.ex);
        rit=st.find(ev.sx);
        it++;
        rit--;
        ll=*rit;
        rr=*it;

        tmp=ev.sx-1-ll;
        if (tmp>=m) ret-=tmp+1-m;
        tmp=rr-1-ev.ex;
        if (tmp>=m) ret-=tmp+1-m;
        tmp=rr-1-ll;
        if (tmp>=m) ret+=tmp+1-m;

        st.erase(ev.sx);
        st.erase(ev.ex);
    }
    else{
        st.insert(ev.sx);
        st.insert(ev.ex);
        it=st.find(ev.ex);
        rit=st.find(ev.sx);
        it++;
        rit--;
        ll=*rit;
        rr=*it;
        tmp=ev.sx-1-ll;
        if (tmp>=m) ret+=tmp+1-m;
        tmp=rr-1-ev.ex;
        if (tmp>=m) ret+=tmp+1-m;
        tmp=rr-1-ll;
        if (tmp>=m) ret-=tmp+1-m;
    }
    return ret;
}

long long work(int n,int tn,int w,int h){
    int i;
    int t,tlen;
    long long sum=0,ret=0;
    st.clear();
    insert(ev[0]);
    if (h>=m){
        sum=h+1-m;
    }
    ret+=sum*(ev[1].t-1);
    for(i=1;i<=tn;){
        t=ev[i].t;
        while(ev[i].t==t){
            sum+=insert(ev[i]);
            ++i;
        }
        tlen=ev[i].t-t;
        ret+=sum*tlen;
    }
    return ret;
}

int n,w,h;

int main(){
    //freopen("bin.txt","r",stdin);
    int i,tn;
    long long ans1,ans2=0;
    while(scanf("%d%d%d%d",&w,&h,&n,&m)!=EOF){
        for(i=1;i<=n;++i){
            scanf("%d%d%d%d",&r[i].sx,&r[i].sy,&r[i].ex,&r[i].ey);
        }
        tn=initeven1(n,w,h);
        ans1=work(n,tn,w,h);
        if (m>1){
            tn=initeven2(n,h,w);
            ans2=work(n,tn,h,w);
        }
        else ans2=0;

        printf("%I64d\n",ans1+ans2);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: