洛谷 P4169 [Violet]天使玩偶/SJY摆棋子

如果只考虑左下角的玩偶这道题就是三维偏序了。那么只要翻转四次,四次 cdq 就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>

inline unsigned read(void){
	unsigned res = 0; char ch = std::getchar();
	while(ch < '0' || ch > '9')
		ch = std::getchar();
	while(ch >= '0' && ch <= '9')
		res = res * 10 + ch - 48, ch = std::getchar();
	return res;
}

const int MAXN = 3e5 + 19, MAXV = 1e6 + 19;

struct Node{
	int t, x, y, dist;
	int q;
	bool operator<(const Node& b)const{
		return t != b.t ? t < b.t : (x != b.x ? x < b.x : y < b.y);
	}
}node[MAXN << 1], tmp[MAXN << 1];

int n, m, ans[MAXN];

class Tarr{
	private:
		int tr[MAXV + 10], n;
	public:
		void clear(void){
			std::memset(tr, 0, sizeof tr);
		}
		void clear(int x){
			for(; x <= n; x += x & -x)
				if(tr[x])
					tr[x] = 0;
				else
					break;
		}
		void set(int size){
			n = size;
		}
		void update(int x, int k){
			for(; x <= n; x += x & -x)
				tr[x] = std::max(tr[x], k);
		}
		int query(int x){
			int res = 0;
			for(; x; x -= x & - x)
				res = std::max(res, tr[x]);
			return res ? res : -0x3f3f3f3f;
		}
}myTree;

void cdq(int l, int r){
	if(l == r)
		return;
	int mid = (l + r) >> 1;
	cdq(l, mid), cdq(mid + 1, r);
	int p = l, q = mid + 1, cnt = l;
	while(p <= mid && q <= r)
		if(node[p].x <= node[q].x){
			if(!node[p].q)
				myTree.update(node[p].y, node[p].x + node[p].y);
			tmp[cnt++] = node[p++];
		}
		else{
			if(node[q].q)
				node[q].dist = std::min(node[q].dist, node[q].x + node[q].y - myTree.query(node[q].y));
			tmp[cnt++] = node[q++];
		}
	while(p <= mid)
		tmp[cnt++] = node[p++];
	while(q <= r){
		if(node[q].q)
			node[q].dist = std::min(node[q].dist, node[q].x + node[q].y - myTree.query(node[q].y));
		tmp[cnt++] = node[q++];
	}
	for(int i = l; i <= mid; ++i)
		if(!node[i].q)
			myTree.clear(node[i].y);
	for(int i = l; i <= r; ++i)
		node[i] = tmp[i];
}

int q;

int main(){
#ifndef ONLINE_JUDGE
	std::freopen("P4169_11.in", "r", stdin);
	std::freopen("P4169_11.out", "w", stdout);
#endif
	n = read(), m = read();
	for(int i = 1; i <= n; ++i)
		node[i].t = 1, node[i].x = read(), node[i].y = read() + 1, node[i].dist = 0;
	for(int i = n + 1; i <= n + m; ++i){
		if(read() == 2)
			node[i].q = ++q;
		node[i].t = i - n + 1, node[i].x = read(), node[i].y = read() + 1, node[i].dist = 0x7fffffff;
	}
	myTree.set(MAXV + 3);
	std::sort(node + 1, node + 1 + n + m);
	cdq(1, n + m);
	for(int i = 1; i <= n + m; ++i)
		node[i].x = MAXV - node[i].x;
	std::sort(node + 1, node + 1 + n + m);
	cdq(1, n + m);
	for(int i = 1; i <= n + m; ++i)
		node[i].x = MAXV - node[i].x, node[i].y = MAXV - node[i].y;
	std::sort(node + 1, node + 1 + n + m);
	cdq(1, n + m);
	for(int i = 1; i <= n + m; ++i)
		node[i].x = MAXV - node[i].x;
	std::sort(node + 1, node + 1 + n + m);
	cdq(1, n + m);
	for(int i = 1; i <= n + m; ++i)
		if(node[i].q)
			ans[node[i].q] = node[i].dist;
	for(int i = 1; i <= q; ++i)
		std::printf("%d\n", ans[i]);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/natsuka/p/12724152.html