您的位置:首页 > 其它

Gym 100942I Manhattan Project (set)

2016-04-03 04:32 363 查看
题意:在一个四维空间内,有三种操作,增加一个点,删除一个点,给定一个点并查询与这个点距离最远点的距离。定义任意两个点之间的距离为他们之间的曼哈顿距离|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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  GYM set