洛谷P6783 【[Ynoi2008]rrusq】 題解
阿新 • • 發佈:2020-10-10
離線詢問,從小到大掃描右端點的同時維護左端點的答案。
記 \(l_i\) 表示第 \(i\) 個點 \((i,p_i)\) 最晚被覆蓋到的時間 .
不難發現我們需要對一個點集的 \(l_i\) 進行賦值,同時維護一個關於 \(l_i\) 的字尾和。
對點建出 KDTree , 每次詢問在 KDTree 上遍歷並打標記,在打標記的同時要把子樹內的所有標記收回。因為收回標記對應著打標記,所以複雜度仍然是 \(\Theta(m)\) 次遍歷 KDTree 的複雜度 , 即 \(\Theta(m\sqrt n)\) 次打標記/收回標記的操作。
現在我們要完成的問題變成了支援 \(\Theta(m\sqrt n)\)
時間複雜度 \(\Theta(n\sqrt m+m\sqrt n)\) , 空間複雜度 \(\Theta(n+m)\)
code :
const int N = 100005,Q = 1000005; struct data_structure{ //O(1)-O(sqrt(m)) int n,m,siz,cur[N],cr[1000],a[N],tag[1000]; inline void init(int nn){ int i; n = nn,siz = max(1,(int)sqrt(n)); for (i = 1; i <= n; ++i) cur[i] = (i-1)/siz+1; m = cur[n]; for (i = 1; i <= m; ++i) cr[i] = min(i*siz,n); } inline void add(int x,int v){ a[x] += v,tag[cur[x]] += v; } inline int ask(int x){ static int tot,i; for (tot = 0,i = cur[x] + 1; i <= m; ++i) tot += tag[i]; for (i = cr[cur[x]]; i >= x; --i) tot += a[i]; return tot; } }DS; int n,y[N],v[N]; int m; struct Mat{ int xl,xr,yl,yr; }mat[N]; int q,ql[Q],ans[Q]; vector<int>G[N]; const int V = N<<3; int id[N],mxx[V],mnx[V],mxy[V],mny[V],sum[V]; inline bool cmp_x(int i,int j){ return i < j; } inline bool cmp_y(int i,int j){ return y[i] < y[j]; } #define lc o<<1 #define rc o<<1|1 inline void Build(int o,int l,int r,int d){ if (l == r){ mxx[o] = mnx[o] = id[l],mxy[o] = mny[o] = y[id[l]],sum[o] = v[id[l]]; return; } int mid = l+r>>1; if (d) nth_element(id+l,id+mid,id+r+1,cmp_x); else nth_element(id+l,id+mid,id+r+1,cmp_y); Build(lc,l,mid,d^1),Build(rc,mid+1,r,d^1); mxx[o] = max(mxx[lc],mxx[rc]); mnx[o] = min(mnx[lc],mnx[rc]); mxy[o] = max(mxy[lc],mxy[rc]); mny[o] = min(mny[lc],mny[rc]); sum[o] = sum[lc] + sum[rc]; } int tag[V]; bool is[V]; int xll,xrr,yll,yrr,tim; inline bool unchk(int o){ return xll > mxx[o] || xrr < mnx[o] || yll > mxy[o] || yrr < mny[o]; } inline bool chk(int o){ return xll <= mnx[o] && mxx[o] <= xrr && yll <= mny[o] && mxy[o] <= yrr; } inline bool chkp(int x){ return xll <= x && x <= xrr && yll <= y[x] && y[x] <= yrr; } inline void clrn(int o){ if (tag[o]) DS.add(tag[o],-sum[o]),tag[o] = 0; } inline void Clr(int o){ if (!is[o]) return; if (tag[o]) DS.add(tag[o],-sum[o]),tag[o] = 0; Clr(lc),Clr(rc),is[o] = 0; } inline void down(int o){ if (tag[o]){ clrn(lc),tag[lc] = tag[o],is[lc] = 1; clrn(rc),tag[rc] = tag[o],is[rc] = 1; tag[o] = 0; } } inline void Add(int o){ if (!o || unchk(o)) return; if (chk(o)){ Clr(o),tag[o] = tim,DS.add(tim,sum[o]),is[o] = 1; return; } down(o),Add(lc),Add(rc),is[o] = 1; } int main(){ register int i,j; read(n); for (i = 1; i <= n; ++i) read(y[i]),read(v[i]),id[i] = i; read(m); for (i = 1; i <= m; ++i) read(mat[i].xl),read(mat[i].xr),read(mat[i].yl),read(mat[i].yr); DS.init(m); read(q); for (i = 1; i <= q; ++i) read(ql[i]),read(j),G[j].push_back(i); Build(1,1,n,0); for (i = 1; i <= m; ++i){ tim = i,xll = mat[i].xl,xrr = mat[i].xr,yll = mat[i].yl,yrr = mat[i].yr; Add(1); for (j = 0; j < G[i].size(); ++j) ans[G[i][j]] = DS.ask(ql[G[i][j]]); } for (i = 1; i <= q; ++i) write(ans[i]),putchar('\n'); return 0; }