【BZOJ2773】ispiti【CDQ分治】【線段樹】
阿新 • • 發佈:2019-01-09
很容易看出來是CDQ分治,但是細節比較多。
令B為x軸,A為y軸...
給x軸排序要按降序排,而且當插入與查詢在同一個點時,要先查詢再插入,這樣就不用維護次小值了。
光給操作離散化了,忘了給點離散化...導致大資料GG。
/* Pigonometry */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 200005, inf = 0x3f3f3f3f; int totx, toty, discx[maxn], discy[maxn], ans[maxn], tr[maxn << 1], mx[maxn << 1]; struct _pos { int x, y; } pos[maxn]; struct _data { int opt, id, no, x, y; } c[maxn], tmp[maxn]; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } inline int findx(int x) { int l = 1, r = totx; while(l <= r) { int mid = l + r >> 1; if(discx[mid] < x) l = mid + 1; else if(discx[mid] == x) return mid; else r = mid - 1; } } inline int findy(int x) { int l = 1, r = toty; while(l <= r) { int mid = l + r >> 1; if(discy[mid] < x) l = mid + 1; else if(discy[mid] == x) return mid; else r = mid - 1; } } inline void pushup(int p) { int l = p << 1, r = p << 1 | 1; if(tr[l] < tr[r]) tr[p] = tr[l], mx[p] = mx[l]; else if(tr[l] > tr[r]) tr[p] = tr[r], mx[p] = mx[r]; else tr[p] = tr[l], mx[p] = mx[l]; } inline void insert(int p, int l, int r, int x, int w, int no) { if(l == r && r == x) { tr[p] = w; mx[p] = no; return; } int mid = l + r >> 1; if(x <= mid) insert(p << 1, l, mid, x, w, no); else insert(p << 1 | 1, mid + 1, r, x, w, no); pushup(p); } inline int query(int p, int l, int r, int x, int y) { if(x <= l && r <= y) return mx[p]; int mid = l + r >> 1, lno = 0, rno = 0; if(x <= mid) lno = query(p << 1, l, mid, x, y); if(y > mid) rno = query(p << 1 | 1, mid + 1, r, x, y); if(pos[lno].x < pos[rno].x) return lno; else if(pos[lno].x > pos[rno].x) return rno; else return lno; } inline void cdq(int l, int r) { if(l == r) return; int mid = l + r >> 1; for(int i = l; i <= r; i++) if(c[i].opt == 1 && c[i].id <= mid) insert(1, 1, toty, c[i].y, c[i].x, c[i].no); else if(c[i].opt == 2 && c[i].id > mid) { int t = query(1, 1, toty, c[i].y, toty); if(!ans[c[i].no]) ans[c[i].no] = t; else if(pos[t].x < pos[ans[c[i].no]].x || (pos[t].x == pos[ans[c[i].no]].x && pos[t].y < pos[ans[c[i].no]].y)) ans[c[i].no] = t; } for(int i = l; i <= r; i++) if(c[i].opt == 1 && c[i].id <= mid) insert(1, 1, toty, c[i].y, inf, 0); int h1 = l, h2 = mid; for(int i = l; i <= r; i++) tmp[c[i].id <= mid ? h1++ : ++h2] = c[i]; for(int i = l; i <= r; i++) c[i] = tmp[i]; cdq(l, mid); cdq(mid + 1, r); } inline bool cmp(_data a, _data b) { return a.x != b.x ? a.x > b.x : a.y != b.y ? a.y > b.y : a.opt > b.opt; } int main() { int T = iread(), n = 0, tot = 0; for(int i = 1; i <= T; i++) { char ch = getchar(); for(; ch != 'D' && ch != 'P'; ch = getchar()); if(ch == 'D') { n++; pos[n].y = iread(); pos[n].x = iread(); c[i] = (_data){1, i, n, pos[n].x, pos[n].y}; discx[++totx] = pos[n].x; discy[++toty] = pos[n].y; } else { int id = iread(); c[i] = (_data){2, i, ++tot, pos[id].x, pos[id].y}; } } pos[0].x = pos[0].y = inf; sort(discx + 1, discx + 1 + totx); totx = unique(discx + 1, discx + 1 + totx) - (discx + 1); sort(discy + 1, discy + 1 + toty); toty = unique(discy + 1, discy + 1 + toty) - (discy + 1); for(int i = 1; i <= n; i++) pos[i].x = findx(pos[i].x), pos[i].y = findy(pos[i].y); for(int i = 1; i <= T; i++) c[i].x = findx(c[i].x), c[i].y = findy(c[i].y); memset(tr, 0x3f, sizeof(tr)); sort(c + 1, c + 1 + T, cmp); cdq(1, T); for(int i = 1; i <= tot; i++) printf(!ans[i] ? "NE\n" : "%d\n", ans[i]); return 0; }