ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

一个10^6行10^6列的网格图,上面有一些牛、花和一些矩形围栏,围栏在格子的边界上,牛和花在格子里,牛只能向下或向右走,牛也不能穿过围栏和地图边界,求每头牛它能到达的花的数量。注意栅栏不会相交
 

Input

第一行一个数f表示矩形围栏的数量。
接下来f行,每行四个数x1,y1,x2,y2,表示(x1,y1)在围栏内部矩形的左上角,(x2,y2)在右下角。
接下来一行一个数m表示花的数量。
接下来m行每行两个数x,y,表示在(x,y)处有一朵花。
接下来一行一个数n表示牛的数量。
接下来n行每行两个数x,y,表示在(x,y)处有一头牛。

Output

总共n行,每行一个数ans,第i个数表示第i头牛能到ans个花。
 
用线段树维护扫描线,从右往左扫描,维护线上每个点能到达的花的个数,然后需要一个大分类。。
对于花,会对一个区间(当前点到上方一个水平围栏)有贡献
围栏右界会清空一段的值,左界同样会清空,但有一些贡献要补回来(围栏下方和右下方区域变得可达)
#include<bits/stdc++.h>
#define G *++ptr
const int N=200007;
char buf[N*100],*ptr=buf-1;
int _(){
    int x=0,c=G;
    while(c<48)c=G;
    while(c>47)x=x*10+c-48,c=G;
    return x;
}
int _l,_r,_a;
struct node{
    private:
    node*lc,*rc;
    int L,M,R,a,cl;
    void clr(){
        cl=1;
        a=0;
    }
    void dn(){
        if(cl){
            lc->clr();
            rc->clr();
            cl=0;
        }
        if(a){
            lc->a+=a;
            rc->a+=a;
            a=0;
        }
    }
    public:
    void get(){
        if(L==R)_a=a;
        else dn(),(_l<=M?lc:rc)->get();
    }
    void clear(){
        if(_l<=L&&R<=_r){
            clr();
            return;
        }
        dn();
        if(_l<=M)lc->clear();
        if(_r>M)rc->clear();
    }
    void add(){
        if(_l<=L&&R<=_r){
            a+=_a;
            return;
        }
        dn();
        if(_l<=M)lc->add();
        if(_r>M)rc->add();
    }
    friend node*build(int L,int R);
}_ns[N*20],*np=_ns,*rt;
node*build(int L,int R){
    node*w=np++;
    w->L=L;w->R=R;
    if(L<R){
        int M=w->M=L+R>>1;
        w->lc=build(L,M);
        w->rc=build(M+1,R);
    }
    return w;
}
int f,m,n,ep=0,ans[N],ss[N];
std::multiset<int>st;
void ins(int x){st.insert(x);}
void del(int x){st.erase(st.find(x));}
int lss(int x){return*--st.upper_bound(x);}
struct ev{
    int x,y1,y2,id,tp;
    void cal(){
        if(tp==1){
            _l=y1,_r=y2;
            rt->clear();
            del(y1);del(y2+1);
            _l=y2+1;
            rt->get();
            _l=y1,_r=y2;
            rt->add();
            _l=lss(y1-1),_r=y1-1;
            _a-=ss[id];
            rt->add();
        }else if(tp==0){
            _l=y1,_r=y2;
            rt->clear();
            ins(y1);ins(y2+1);
            _l=y2+1;
            rt->get();
            ss[id]=_a;
        }else if(tp==2){
            _l=lss(y1),_r=y1,_a=1;
            rt->add();
        }else{
            _l=y1;
            rt->get();
            ans[id]=_a;
        }
    }
    bool operator<(const ev&e)const{return x!=e.x?x>e.x:tp<e.tp;}
}e[N*5];
int main(){
    fread(buf,1,sizeof(buf),stdin)[buf]=0;
    st.insert(0);
    f=_();
    for(int i=1;i<=f;++i){
        int x1=_(),y1=_(),x2=_(),y2=_();
        e[ep++]=(ev){x1-1,y1,y2,i,1};
        e[ep++]=(ev){x2,y1,y2,i,0};
    }
    m=_();
    for(int i=1;i<=m;++i){
        int x=_(),y=_();
        e[ep++]=(ev){x,y,y,i,2};
    }
    n=_();
    for(int i=1;i<=n;++i){
        int x=_(),y=_();
        e[ep++]=(ev){x,y,y,i,3};
    }
    rt=build(0,1000000);
    std::sort(e,e+ep);
    for(int i=0;i<ep;++i)e[i].cal();
    for(int i=1;i<=n;++i)printf("%d\n",ans[i]);
    return 0;
}

 

posted on 2017-03-23 21:14  nul  阅读(426)  评论(3编辑  收藏  举报