#include <bits/stdc++.h>
int64_t n, m, k;
struct point_t
{
int64_t x;
int64_t y;
};
struct line_t
{
int64_t bound;
int64_t k;
int64_t b;
};
std::vector<point_t> point;
std::vector<int64_t> point_x, point_y;
std::vector<line_t> line_x, line_y;
auto cmp = [](point_t a, point_t b)
{
if (a.x < b.x)
return true;
else if (a.x > b.x)
return false;
return a.y < b.y;
};
auto cmp_line = [](line_t a, line_t b)
{
return a.bound < b.bound;
};
inline int64_t calculate(int64_t px, int64_t py)
{
int64_t ans = 0;
for (int i = 0; i < k; i++)
ans += abs(point[i].x - px) + abs(point[i].y - py);
return ans;
}
inline int64_t calculate_x(int64_t px)
{
int64_t ans = 0;
for (int i = 0; i < k; i++)
ans += abs(point[i].x - px);
return ans;
}
inline int64_t calculate_y(int64_t py)
{
int64_t ans = 0;
for (int i = 0; i < k; i++)
ans += abs(point[i].y - py);
return ans;
}
inline line_t get_line(point_t a, point_t b)
{
return (line_t){b.x, (a.y - b.y) / (a.x - b.x), (b.y * a.x - a.y * b.x) / (a.x - b.x)};
}
void init()
{
for (auto &&i : point)
{
point_x.push_back(i.x);
point_y.push_back(i.y);
}
auto it = point_x.begin();
auto prev_it = it;
int64_t prev = calculate_x(*it);
line_x.push_back((line_t){*it, -k, prev + k * *it});
int64_t next = prev, point_sum = 0;
while ((it = std::upper_bound(point_x.begin(), point_x.end(), *it)) != point_x.end())
{
point_sum = std::distance(point_x.begin(), it);
next += point_sum * (*it - *prev_it);
next -= (k - point_sum) * (*it - *prev_it);
line_x.push_back(get_line((point_t){*prev_it, prev}, (point_t){*it, next}));
prev = next;
prev_it = it;
}
line_x.push_back((line_t){n, k, prev - k* *prev_it});
std::sort(point_y.begin(), point_y.end());
it = point_y.begin();
prev_it = it;
prev = calculate_y(*it);
line_y.push_back((line_t){*it, -k, prev + k * *it});
next = prev, point_sum = 0;
while ((it = std::upper_bound(point_y.begin(), point_y.end(), *it)) != point_y.end())
{
point_sum = std::distance(point_y.begin(), it);
next += point_sum * (*it - *prev_it);
next -= (k - point_sum) * (*it - *prev_it);
line_y.push_back(get_line((point_t){*prev_it, prev}, (point_t){*it, next}));
prev = next;
prev_it = it;
}
line_y.push_back((line_t){m, k, prev - k* *prev_it});
}
inline int64_t x_sum(int64_t x)
{
auto it = std::lower_bound(line_x.begin(), line_x.end(), (line_t){x, 0, 0}, cmp_line);
return it->k * x + it->b;
}
inline int64_t y_sum(int64_t y)
{
auto it = std::lower_bound(line_y.begin(), line_y.end(), (line_t){y, 0, 0}, cmp_line);
return it->k * y + it->b;
}
inline int64_t sum(int64_t x, int64_t y)
{
return x_sum(x) + y_sum(y);
}
inline bool valid(int64_t x, int64_t y)
{
return 1 <= x && x <= n && 1 <= y && y <= m;
}
inline bool exist(int64_t x, int64_t y)
{
auto it = std::lower_bound(point.begin(), point.end(), (point_t){x, y}, cmp);
return it != point.end() && it->x == x && it->y == y;
}
int64_t ans = 0;
inline void push_vertex(int64_t x, int64_t y)
{
if (!exist(x + 1, y) && valid(x + 1, y))
{
int64_t result = sum(x + 1, y);
// assert(result == calculate(x + 1, y));
if (ans < result)
ans = result;
}
if (!exist(x - 1, y) && valid(x - 1, y))
{
int64_t result = sum(x - 1, y);
// assert(result == calculate(x - 1, y));
if (ans < result)
ans = result;
}
if (!exist(x, y + 1) && valid(x, y + 1))
{
int64_t result = sum(x, y + 1);
// assert(result == calculate(x, y + 1));
if (ans < result)
ans = result;
}
if (!exist(x, y - 1) && valid(x, y - 1))
{
int64_t result = sum(x, y - 1);
// assert(result == calculate(x, y - 1));
if (ans < result)
ans = result;
}
}
void solve_ac()
{
point.resize(k);
for (int i = 0; i < k; i++)
scanf("%ld %ld", &point[i].x, &point[i].y);
std::sort(point.begin(), point.end(), cmp);
init();
int64_t last = 0;
int64_t id = 0;
for (int i = 0; i < k; i++)
push_vertex(point[i].x, point[i].y);
if (!exist(1, 1) && valid(1, 1))
{
int64_t result = sum(1, 1);
if (ans < result)
ans = result;
}
if (!exist(1, m) && valid(1, m))
{
int64_t result = sum(1, m);
if (ans < result)
ans = result;
}
if (!exist(n, 1) && valid(n, 1))
{
int64_t result = sum(n, 1);
if (ans < result)
ans = result;
}
if (!exist(n, m) && valid(n, m))
{
int64_t result = sum(n, m);
if (ans < result)
ans = result;
}
printf("%ld", ans);
}
int main()
{
scanf("%ld %ld %ld", &n, &m, &k);
solve_ac();
return 0;
}
最后一个subtask WA了#43~#47,确定是sum()的问题。
我的思路是,sum()函数是计算曼哈顿距离之和的,我先是预处理分段求出x轴绝对值函数kx+b与y轴绝对值函数kx+b,结果跑到#43~#47不知为何sum()似乎算错了,求大佬指出问题。