[TJOI2013]松鼠聚会【切比雪夫距离转换曼哈顿距离】

题目链接


  首先,愚人节那天,暴力斩获30分,(暴力法真好用!

  然后,讲一下解题的思路吧,主要是怎样转换切比雪夫距离这里要有神奇的方法。

首先,我们先列举一下两点间切比雪夫距离的求解公式:

Qdis(1, 2) = max(abs(x_1 - x_2), abs(y_1 - y_2))

Qdis(i, j)指的是i、j两点的切比雪夫距离

于是,我们再用一些数学上的思维来拆解这个等式关系

max(abs(x_1 - x_2), abs(y_1 - y_2)) = \frac{1}{2} \left [ abs(x_1 - x_2 + y_1 - y_2) + abs(x_1 - x_2 - y_1 + y_2) \right ]

这样的做法,是为了我们去掉最大值max()符号

之后,我们发现,似乎变成了新的坐标,我们移项来看

abs(x_1 - x_2 + y_1 - y_2) + abs(x_1 - x_2 - y_1 + y_2) = abs(x_1 + y_1 - (x_2 + y_2)) + abs(x_1 - y_1 + (x_2 - y_2))

我的天呐,神不神奇?

等式右边,不就是曼哈顿距离了嘛。

只是原来的(x, y)\rightarrow (\frac{x + y}{2}, \frac{x - y}{2})做了这样的转换

好神奇!!!

那么,原来的问题,就变成了如何求解各点到其余所有点的距离和了,二维偏序基础!

解决二维偏序问题,我们首先对第一维进行排序,就对x进行升序排序吧,然后就可以O(1)的求解其中一维了(x坐标)。

然后,利用树状数组+离散化的操作,我们处理第二维。

这样的处理方法是为了去掉绝对值,变成绝对大减去绝对小这样的形式了。

当然,主席树等数据结构,也是可以用以维护的。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define eps 1e-8
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e5 + 7;
int N, _UP;
ll sum[maxN] = {0}, all_y = 0, tx, ty;
struct node
{
    ll x, y;
    node(ll a=0, ll b=0):x(a), y(b) {}
    inline void In()
    {
        scanf("%lld%lld", &tx, &ty);
        x = tx + ty; y = tx - ty;
    }
    friend bool operator < (node e1, node e2) { return e1.x < e2.x; }
} a[maxN];
ll tree[maxN], num[maxN], Lsan[maxN];
inline void update(int x, ll val)
{
    while(x <= _UP)
    {
        tree[x] += val;
        num[x] ++;
        x += lowbit(x);
    }
}
inline void query(int x, ll &ss, ll &sz)
{
    ss = 0; sz = 0;
    while(x)
    {
        ss += tree[x]; sz += num[x];
        x -= lowbit(x);
    }
}
int main()
{
    scanf("%d", &N);
    for(int i=1; i<=N; i++) { a[i].In(); Lsan[i] = a[i].y; }
    sort(a + 1, a + N + 1);
    sort(Lsan + 1, Lsan + N + 1);
    _UP = (int)(unique(Lsan + 1, Lsan + N + 1) - Lsan - 1);
    for(int i=1, id; i<=N; i++)
    {
        sum[i] = sum[i - 1] + a[i].x;
        all_y += a[i].y;
        id = (int)(lower_bound(Lsan + 1, Lsan + _UP + 1, a[i].y) - Lsan);
        update(id, a[i].y);
    }
    ll ans = INF, tmp;
    ll ss, sz;
    for(int i=1, id; i<=N; i++)
    {
        tmp = (i - 1LL) * a[i].x - sum[i - 1] + (sum[N] - sum[i]) - 1LL * (N - i) * a[i].x;
        id = (int)(lower_bound(Lsan + 1, Lsan + _UP + 1, a[i].y) - Lsan);
        query(id, ss, sz);
        tmp += sz * a[i].y - ss + all_y - ss - 1LL * (N - sz) * a[i].y;
        ans = min(ans, tmp);
    }
    printf("%lld\n", ans >> 1LL);
    return 0;
}
发布了891 篇原创文章 · 获赞 1066 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/105286830