【2011集训队出题】信号塔

Description:

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);
}

你可能感兴趣的:(信息学,几何,计算几何)