好题
从右往左扫 我们在线段树上维护
fy
f
的含义
- 如果下方是栅栏 那么
fy 就是 (x,y) 的答案- 否则 fy 是 (x,y) 比 (x,y+1) 多出来的答案
本质是一个查分 查询一头牛的答案就是往下累加 f 直到碰到栅栏
那么碰到牛就查询 碰到花就加一 关键是碰到栅栏
(xl,xr,yl,yr)
在 xr 处 [yl,yr] 清空 yl−1 处要加上 yl 的答案 同时记录下 yr+1 的答案
在 xl−1 处 [yl,yr] 清空 同时 yl−1 要减去在 xr 时记录的 yr+1 的答案 防止没有了栅栏的阻挡重复计算#include<cstdio> #include<cstdlib> #include<algorithm> #include<set> using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int M=1000005; int m=1000000; int T[M<<2],F[M<<2]; inline void modify(int x,int l,int r,int ql,int qr){ if (ql<=l && r<=qr){ T[x]=0; F[x]=1; return; } if (F[x]) T[x<<1]=T[x<<1|1]=0,F[x<<1]=F[x<<1|1]=1,F[x]=0; int mid=(l+r)>>1; if (ql<=mid) modify(x<<1,l,mid,ql,qr); if (qr>mid) modify(x<<1|1,mid+1,r,ql,qr); T[x]=T[x<<1]+T[x<<1|1]; } inline void add(int x,int l,int r,int t,int a){ if (l==r) return void(T[x]+=a); if (F[x]) T[x<<1]=T[x<<1|1]=0,F[x<<1]=F[x<<1|1]=1,F[x]=0; int mid=(l+r)>>1; if (t<=mid) add(x<<1,l,mid,t,a); else add(x<<1|1,mid+1,r,t,a); T[x]=T[x<<1]+T[x<<1|1]; } inline int query(int x,int l,int r,int ql,int qr){ if (ql<=l && r<=qr) return T[x]; if (F[x]) T[x<<1]=T[x<<1|1]=0,F[x<<1]=F[x<<1|1]=1,F[x]=0; int ret=0,mid=(l+r)>>1; if (ql<=mid) ret+=query(x<<1,l,mid,ql,qr); if (qr>mid) ret+=query(x<<1|1,mid+1,r,ql,qr); return ret; } const int N=200005; struct event{ int f,x,y,y2,idx; // f : 1 left 2 right 3 flower 4 cow event(int f=0,int x=0,int y=0,int y2=0,int idx=0):f(f),x(x),y(y),y2(y2),idx(idx) { } bool operator < (const event &B) const{ return x==B.x?(!(f<=2 && B.f<=2)?f<B.f:y<B.y):x>B.x; } }ev[N<<2]; int tot; set<int> fen; int tmp[N]; int ans[N]; inline int Ans(int y){ int y2=*fen.lower_bound(y); return query(1,1,m,y,min(y2,m)); } int main(){ int n,x,y,x2,y2; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); for (int i=1;i<=n;i++){ read(x); read(y); read(x2); read(y2); swap(x,y); swap(x2,y2); ev[++tot]=event(1,x-1,y,y2,i); ev[++tot]=event(2,x2,y,y2,i); } read(n); for (int i=1;i<=n;i++){ read(x); read(y); swap(x,y); ev[++tot]=event(3,x,y,0,i); } read(n); for (int i=1;i<=n;i++){ read(x); read(y); swap(x,y); ev[++tot]=event(4,x,y,0,i); } sort(ev+1,ev+tot+1); fen.insert(m+1); for (int i=1;i<=tot;i++) if (ev[i].f==1){ modify(1,1,m,ev[i].y,ev[i].y2); if (ev[i].y-1) add(1,1,m,ev[i].y-1,-tmp[ev[i].idx]); if (ev[i].y-1) fen.erase(ev[i].y-1); fen.erase(ev[i].y2); }else if (ev[i].f==2){ int ret=Ans(ev[i].y); tmp[ev[i].idx]=Ans(ev[i].y2+1); modify(1,1,m,ev[i].y,ev[i].y2); if (ev[i].y-1) add(1,1,m,ev[i].y-1,ret); if (ev[i].y-1) fen.insert(ev[i].y-1); fen.insert(ev[i].y2); }else if (ev[i].f==3) add(1,1,m,ev[i].y,1); else ans[ev[i].idx]=Ans(ev[i].y); for (int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }