lanwuni接到一个任务,在C市建立N个信号塔来完成城市中的通讯任务。 假设C市是一个坐标范围[-2000000,2000000]的网格,一些整点上有用户,你也可以在整点上建立信号塔。一个点上可以建立多座。 在C市,两点之间的距离是曼哈顿距离,也就是横纵坐标差值之和。每个信号塔都有一个半径Di,表示与i曼哈顿距离不超过Di的地方都能被这个信号塔的信号覆盖到。 建立信号塔要满足一些性质: 1. 每个信号塔有一定的用户,lanwuni要把信号塔建立在某个地方,使得属于该塔的用户都能被信号覆盖到; 2. 信号塔有一定等级和安装限制,所以,第i号信号塔能覆盖的所有整点,必须也被第i+1号信号塔覆盖到。即使这个整点上没有用户。 现在告诉你每个信号塔的半径,以及每个信号塔的用户,请你帮lanwuni谋划一下应该把这N个信号塔建立在什么地方。
100%的数据中,1<=N,M<=100000,|Xi|,|Yi|,|Di|<=1000000。
题目附有Special Judge
首先对每个用户,合法的信号塔的位置是一个菱形。
那么这样一直合并,最后是一个平行四边形。
但是不好合并。
所以先把所有点旋转45°,避免小数运算,乘上 2√
变成了矩形合并问题,去min、max就行了。
求出最大的信号塔的范围后,随便选一个点,注意要抱证奇偶性相同,不然还回去就不存在。
选出来后,再倒退,去约束范围。
#include
#include
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
using namespace std;
const int N = 1e5 + 5;
struct node {
int u, x, y;
} a[N], as[N];
int n, m, x, y, d[N];
struct jx {
int z, y, s, x;
} b[N], c[N], p;
bool cmp(node a, node b) {return a.u < b.u;}
void bin(jx &a, jx b) {
a.z = max(a.z, b.z); a.x = max(a.x, b.x);
a.y = min(a.y, b.y); a.s = min(a.s, b.s);
}
node G(jx a) {
node b;
b.x = a.z; b.y = a.x;
if((b.y - b.x) % 2) {
if(a.z != a.y) b.x ++; else b.y ++;
}
return b;
}
int main() {
scanf("%d %d", &n, &m);
fo(i, 1, n) scanf("%d", &d[i]);
fo(i, 1, m) scanf("%d %d %d", &a[i].u, &a[i].x, &a[i].y);
fo(i, 1, n) {
b[i].z = b[i].x = -1e8;
b[i].y = b[i].s = 1e8;
}
fo(i, 1, m) {
x = a[i].x, y = a[i].y;
a[i].x = x - y; a[i].y = x + y;
int c = d[a[i].u];
p.z = a[i].x - c; p.y = a[i].x + c;
p.x = a[i].y - c; p.s = a[i].y + c;
bin(b[a[i].u], p);
}
c[n] = b[n];
fd(i, n - 1, 1) {
int r = d[i + 1] - d[i];
c[i] = b[i];
p.z = c[i + 1].z - r;
p.y = c[i + 1].y + r;
p.x = c[i + 1].x - r;
p.s = c[i + 1].s + r;
bin(c[i], p);
}
fo(i, 1, n) {
as[i] = G(c[i]);
if(i == n) continue;
int r = d[i + 1] - d[i];
p.z = as[i].x - r;
p.y = as[i].x + r;
p.x = as[i].y - r;
p.s = as[i].y + r;
bin(c[i + 1], p);
}
fo(i, 1, n) printf("%d %d\n", (as[i].x + as[i].y) / 2, (-as[i].x + as[i].y) / 2);
}