【BZOJ2773】ispiti【CDQ分治】【线段树】

【题目链接】

很容易看出来是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;
}


你可能感兴趣的:(【BZOJ2773】ispiti【CDQ分治】【线段树】)