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