hdu 4052 Adding New Machine,set

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;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章