-
考慮將寶石和詢問點定位到唯一一個極小的包涵它的矩形,這個可以通過掃描線解決
我的做法是考慮左邊第一個包涵它的矩陣,用線段樹維護,每個結點維護一個棧
同時可以把矩形定位到唯一一個矩形 -
在每個矩形中處理,我們需要減去兩個階梯形的東西
- 考慮從後向前掃描線維護這個階梯,每遇到一個右邊界就將管轄區間 的全部放到 ,然後查詢是一個後綴區間查詢(不考慮下階梯),接下來的做法是最開始只考慮了右階梯假掉後產生的,設只考慮右階梯的答案爲 ,只考慮下階梯的答案是 ,兩個都不考慮的爲 ,那麼簡單容斥,答案就是 ,處理下階梯按 掃描線即可
#include<bits/stdc++.h>
#define cs const
#define pb push_back
#define fi first
#define se second
using namespace std;
namespace IO{
cs int Rlen=1<<22|1;
inline char gc(){
static char buf[Rlen], *p1, *p2;
(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
return p1==p2?EOF:*p1++;
}
int read(){
int x=0; char c=gc(); bool f=false;
while(!isdigit(c)) f=c=='-', c=gc();
while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
return f?-x:x;
}
} using namespace IO;
cs int N = 2e5 + 50;
cs int A = 1e6;
typedef pair<int, int> pi;
struct pnt{
int x, y, c, blk, dn;
bool operator < (cs pnt &a) cs{
return x<a.x||(x==a.x&&y<a.y); }
};
struct box{
int x, l, r, c;
bool operator < (cs box &a) cs{
return x<a.x||(x==a.x&&l<a.l); }
};
struct mem{ int x, y, l, r; };
mem bin[N];
int blk[N];
int n, m, q, as[N];
pnt a[N], b[N];
box c[N<<1]; int ct;
struct atom{ int opt, c, x, l, r; };
vector<atom> S[N];
vector<atom> T[N];
namespace zkw{
cs int N = 1 << 20;
vector<pi> S[N<<1];
void ins(int l, int r, int v, int c){
for(l+=N-1,r+=N+1; l^r^1; l>>=1,r>>=1){
if(l&1^1) S[l^1].pb(pi(v,c));
if(r&1) S[r^1].pb(pi(v,c));
}
}
void pop(int l, int r){
for(l+=N-1,r+=N+1; l^r^1; l>>=1,r>>=1){
if(l&1^1) S[l^1].pop_back();
if(r&1) S[r^1].pop_back();
}
}
int qry(int x){
int v=-1, c=0;
for(x+=N; x; x>>=1){
if(!S[x].empty() && S[x].back().fi > v)
v = S[x].back().fi, c = S[x].back().se;
} return c;
}
}
void pre_work(pnt *a, int n){
for(int l=1,r=1,j=0; l<=ct; l=r){
while(c[r].x == c[l].x){
if(c[r].c > 0){
if(!blk[c[r].c]) blk[c[r].c] = zkw :: qry(c[r].l);
zkw :: ins(c[r].l,c[r].r,c[r].x,c[r].c);
} else zkw :: pop(c[r].l,c[r].r); ++r;
} while(j < n && a[j+1].x < c[r].x) ++j, a[j].blk = zkw :: qry(a[j].y);
}
}
struct cp{
int x, c; cp(int _x=0, int _c=0){ x=_x; c=_c; }
bool operator < (cs cp &a) cs{ return x < a.x || (x == a.x && c < a.c); };
};
void sub_work(pnt *a, int n){ // work for down
static multiset<cp> St;
for(int l=1,r=1,j=0; l<=ct; l=r){
while(c[r].x == c[l].x){
if(c[r].c > 0) St.insert(cp(c[r].r+1,c[r].c)), St.insert(cp(c[r].l,c[r].c));
else St.erase(St.find(cp(c[r].r+1,-c[r].c))), St.erase(St.find(cp(c[r].l,-c[r].c))); ++r;
}
while(j < n && a[j+1].x < c[r].x){
++j; auto t = St.upper_bound(cp(a[j].y,0));
assert(t != St.end());
a[j].dn = t->c;
}
}
}
namespace SGT{
cs int N = A << 2;
#define mid ((l+r)>>1)
bool c[N]; int sm[N];
void pushup(int x){ sm[x] = sm[x<<1] + sm[x<<1|1]; }
void cov(int x){ c[x] = true; sm[x] = 0; }
void down(int x){ if(c[x]) cov(x<<1), cov(x<<1|1), c[x]=0; }
void ins(int x, int l, int r, int p, int v){
if(p > A) return; if(l==r) return sm[x]+=v,void(); down(x);
(p<=mid) ? ins(x<<1,l,mid,p,v) : ins(x<<1|1,mid+1,r,p,v);
pushup(x);
}
void mdf(int x, int l, int r, int L, int R){
if(L<=l&&r<=R) return cov(x),void(); down(x);
if(L<=mid) mdf(x<<1,l,mid,L,R);
if(R>mid) mdf(x<<1|1,mid+1,r,L,R); pushup(x);
}
int qry(int x, int l, int r, int L, int R){
if(L<=l&&r<=R) return sm[x]; down(x); int as=0;
if(L<=mid) as+=qry(x<<1,l,mid,L,R);
if(R>mid) as+=qry(x<<1|1,mid+1,r,L,R); return as;
}
}
void work(vector<atom> &S){
sort(S.begin(),S.end(),[](cs atom &a, cs atom &b){
return a.x > b.x || (a.x == b.x && a.opt < b.opt);
}); SGT::cov(1);
for(auto t : S){
if(t.opt == 0){
int Sm = SGT::qry(1,1,A,t.l,t.r);
SGT::mdf(1,1,A,t.l,t.r); if(t.l>1) SGT::ins(1,1,A,t.l-1,Sm);
}
if(t.opt == 1) SGT::ins(1,1,A,t.l,1);
if(t.opt == 2) as[t.c] += SGT::qry(1,1,A,t.l,A);//, cout<<t.c<<" "<<as[t.c]<<endl;
} S.clear();
}
void dec_work(vector<atom> &S){
sort(S.begin(),S.end(),[](cs atom &a, cs atom &b){
return a.x > b.x || (a.x == b.x && a.opt < b.opt);
}); SGT::cov(1);
for(auto t : S){
if(t.opt == 1) SGT::ins(1,1,A,t.l,1);
if(t.opt == 2) as[t.c] -= SGT::qry(1,1,A,t.l,A);//, cout << t.c<<" "<<as[t.c] << endl;
} //S.clear();
}
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
// freopen("my.out","w",stdout);
#endif
n=read();
for(int i=1,x,y,l,r; i<=n; i++){
l=read(), x=read(), r=read(), y=read();
c[++ct] = (box){x,l,r,i}; c[++ct] = (box){y+1,l,r,-i};
bin[i]=(mem){x,y,l,r};
// cout<<x<<" "<<l<<" "<<r<<endl;
} ++n; c[++ct] = (box){0,1,A,n}; c[++ct] = (box){A+1,1,A,-n};
m=read(); for(int i=1; i<=m; i++) a[i]=(pnt){read(),read()},swap(a[i].x,a[i].y);
q=read(); for(int i=1; i<=q; i++) b[i]=(pnt){read(),read(),i},swap(b[i].x,b[i].y);
sort(c+1, c+ct+1);
sort(a+1, a+m+1);
sort(b+1, b+q+1);
pre_work(a,m);
pre_work(b,q);
sub_work(b,q);
// for(int i=1; i<=n; i++) cout<<b[i].blk<<endl;
for(int i=1; i<=m; i++)
S[a[i].blk].pb({1,0,a[i].x,a[i].y,0});
for(int i=1; i<=q; i++)
S[b[i].blk].pb({2,b[i].c,b[i].x,b[i].y,0});
for(int i=1; i<=ct; i++) if(c[i].c<0 && blk[-c[i].c])
S[blk[-c[i].c]].pb({0,0,c[i].x-1,c[i].l,c[i].r});
for(int i=1; i<=n; i++) if(!S[i].empty()) work(S[i]);
// for(int i=1; i<=q; i++) cout<<b[i].dn<<endl;
for(int i=1; i<=m; i++)
S[a[i].blk].pb({1,0,a[i].y,a[i].x,0});
for(int i=1; i<=q; i++)
S[b[i].blk].pb({2,b[i].c,b[i].y,b[i].x,0});
for(int i=1; i<=n; i++) if(blk[i])
S[blk[i]].pb({0,i,bin[i].r,bin[i].x,bin[i].y});
for(int i=1; i<=n; i++) if(!S[i].empty()) dec_work(S[i]), work(S[i]);
for(int i=1; i<=q; i++) cout<<as[i]<<'\n';
return 0;
}