1. 程式人生 > >[TJOI2013]松鼠聚會(枚舉)

[TJOI2013]松鼠聚會(枚舉)

題目 [] 聽說 絕對值 include 一個點 turn i++ getchar

[TJOI2013]松鼠聚會

題目描述

草原上住著一群小松鼠,每個小松鼠都有一個家。時間長了,大家覺得應該聚一聚。但是草原非常大,松鼠們都很頭疼應該在誰家聚會才最合理。

每個小松鼠的家可以用一個點x,y表示,兩個點的距離定義為點(x,y)和它周圍的8個點(x-1,y)(x+1,y),(x,y-1),(x,y+1).(x-1,y+1),(x-1,y-1),(x+1,y+1),(x+1,y-1)距離為1。

輸入輸出格式

輸入格式:

第一行是一個整數N,表示有多少只松鼠。接下來N行,第i行是兩個整數x和y,表示松鼠i的家的坐標

輸出格式:

一個整數,表示松鼠為了聚會走的路程和最小是多少。

輸入輸出樣例

輸入樣例#1:

6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2

輸出樣例#1:

20

輸入樣例#2:

6
0 0
2 0
-5 -2
2 -2
-1 2
4 0

輸出樣例#2:

15

說明

樣例解釋

在第一個樣例中,松鼠在第二只松鼠家(-1,-2)聚會;在第二個樣例中,松鼠在第一只松鼠家(0.0)聚會。

數據範圍

30%的數據,0 ≤ N ≤ 1000

100%的數據,0 ≤ N ≤ 100000; ?10^9 ≤ x, y ≤ 10^9

第一次聽說切比雪夫距離這個東西,它可以這樣與曼哈頓距離轉換。

將一個點 (x,y) 的坐標變為 \((x+y,x?y)\) 後,原坐標系中的曼哈頓距離 = 新坐標系中的切比雪夫距離
將一個點 (x,y) 的坐標變為 \((\frac{x+y}{2},\frac{x-y}{2})\)

後,原坐標系中的切比雪夫距離 = 新坐標系中的曼哈頓距離
於是我們把原坐標系轉化一下,轉成更加熟悉的曼哈頓距離。

考慮枚舉在哪只松鼠家聚會,聚會的路程為\(\sum|X_i-X|+|Y_i-Y|\),但是這樣絕對值很難處理。我們可以把X[],Y[]排序,然後查找一下X,Y位置,通過前綴和處理一下就能快速算答案了。

為什麽最小的點答案都會超過1<<40???
然後順序加會long long,換一下加減法順序就過了???

#include<bits/stdc++.h>
#define lll long long
using namespace std;
lll read(){
    lll x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*w;
}
const lll N=100010;
lll n,p,q,sx,sy,ans=(1ll<<62);
lll x[N],y[N],xx[N],yy[N],sumx[N],sumy[N];
lll check1(lll v){
    lll l=1,r=n;
    while(l<r){
        lll mid=(l+r)/2;
        if(x[mid]>=v)r=mid;
        else l=mid+1;
    }return l;
}
lll check2(lll v){
    lll l=1,r=n;
    while(l<r){
        lll mid=(l+r)/2;
        if(y[mid]>=v)r=mid;
        else l=mid+1;
    }return l;
}
int main(){
    n=read();
    for(lll i=1;i<=n;i++){
        p=read();q=read();
        xx[i]=x[i]=p+q;yy[i]=y[i]=p-q;
    }
    sort(x+1,x+1+n);sort(y+1,y+1+n);
    for(lll i=1;i<=n;i++)
        sumx[i]=sumx[i-1]+x[i],sumy[i]=sumy[i-1]+y[i];
    for(lll i=1;i<=n;i++){
        lll p1=check1(xx[i]),p2=check2(yy[i]);
        sx=sumx[n]-sumx[p1]-(n-p1)*xx[i]+p1*xx[i]-sumx[p1];
        sy=sumy[n]-sumy[p2]-(n-p2)*yy[i]+p2*yy[i]-sumy[p2];
        ans=min(ans,sx+sy);
    }printf("%lld\n",ans/2);
}

[TJOI2013]松鼠聚會(枚舉)