Gym 100942I Manhattan Project (set)

题意:在一个四维空间内,有三种操作,增加一个点,删除一个点,给定一个点并查询与这个点距离最远点的距离。定义任意两个点之间的距离为他们之间的曼哈顿距离|x1 - y1| + |x2 - y2| + |x3 - y3| + |x4 - y4|.。

思路:这道题的关键是如何处理绝对值符号,因为对于任意两个点,一共可能有16种运算可能。

解决这个问题可以通过开16个优先队列来解决,然后再用一个set记录每个点是否存在。

每个优先队列t里规定一种操作顺序,对于新加的每个点,将它添加到每一个优先队列中,因为在每一个优先队列中运算规则已经确定了,所以可以根据这种运算顺序计算的权值排序,虽然这样不能保证每个优先队列中的点对于一个查询都是符合当前运算规则的点,但是可以保证的是对于一次询问,最优解一定在相应的优先队列的队首,然后就是判断这个元素是否之前被删掉,结合set就可以解决这个问题。

#include<bits/stdc++.h>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

//const int MAXN = 5000000 + 5;
//const int INF = 0x3f3f3f3f;
struct Node
{
	int x[4];
	bool operator < (const Node& A) const {
		for (int i = 0; i < 4; i++)
			if (x[i] != A.x[i])
				return x[i] < A.x[i];
		return false;
	}
};
int n;
set<Node> s;
priority_queue< pair<int, Node> > pq[16];

int cal_dis(const Node& A, const Node& B) {
	int ans = 0;
	for (int i = 0; i < 4; i++)
		ans += abs(B.x[i]-A.x[i]);
	return ans;
}
void ins(Node node) {
	s.insert(node);
	for (int i = 0; i < 16; i++) {
		int val = 0;
		for (int j = 0; j < 4; j++) {
			if (i&(1<<j))
				val += node.x[j];
			else val -= node.x[j];
		}
		pq[i].push(mp(val, node));
	}
}
void del(Node node) {
	s.erase(node);
}
int query(Node node) {
	int ans = 0;
	for (int i = 0; i < 16; i++) {
		while (!pq[i].empty()) {
			Node t = pq[i].top().second;
			if (!s.count(t)) {
				pq[i].pop();
			}
			else {
				ans = max(ans, cal_dis(t, node));
				break;
			}
		}
	}
	return ans;
}

int main()
{
    //freopen("input.txt", "r", stdin);
	scanf("%d", &n);
	int q;
	Node tmp;
	for (int i = 1; i <= n; i++) {
		scanf("%d%d%d%d%d", &q, &tmp.x[0], &tmp.x[1], &tmp.x[2], &tmp.x[3]);
		if (q == 1) ins(tmp);
		else if (q == 2) del(tmp);
		else printf("%d\n", query(tmp));
	}
    return 0;
}
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值