@PanMingjun
2018-09-13T12:19:56.000000Z
字数 2292
阅读 650
大意:
二维平面给n个点,在x轴上找一个点使它到离它最近的k个点的曼哈顿距离之和最小
个人题解:
先看问题的简化版,在一维平面(比如x轴)上给个点,找一个点使它到所有点的距离之和最小,设满足条件的点为易证
考虑二维情况下,如果我们选定的点为,记离它最近的k个点构成的集合为,则到集合中所有点的曼哈顿距离之和为
在二维情况下在x轴上选点和一维同理,最小值一定在某个满足有个点且有个点满足,易得,然后对每个求出它左边有个点和右边有个点的情况加一下取个
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define ull unsigned long long
#define EPS 1e-8
#define IOS ios_base::sync_with_stdio(0); cin.tie(0)
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
const double pi = acos(-1.0);
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f*x;
}
void write(ll a){
if (a<0) putchar('-'),a=-a;
if (a>=10) write(a/10); putchar(a%10+'0');
}
const ll INF=1e18;
void solve(vector<pll>& p,vector<ll> &ans,ll num,bool flag){
priority_queue<ll> pq;
ll sum=0;
for(auto& ite:p){
ll x=ite.first,y=ite.second;
if(flag){
if((int)pq.size()==num){
ans.push_back(num*x+sum);
}else{
ans.push_back(INF);
}
}
sum+=y-x;
pq.push(y-x);
while((int)pq.size()>num){
sum-=pq.top();
pq.pop();
}
if(!flag){
if((int)pq.size()==num){
ans.push_back(num*x+sum);
}else{
ans.push_back(INF);
}
}
}
}
int main()
{
#ifdef TEST
freopen("input.txt","r",stdin);
#endif
ll n,k;
cin>>n>>k;
vector<pll> points(n);
for(auto&ite :points){
cin>>ite.first>>ite.second;
}
sort(points.begin(),points.end());
vector<ll> left,right;
solve(points,left,k>>1,true);
reverse(points.begin(),points.end());
for(auto &ite:points){
ite.first*=-1;
}
solve(points,right,k-(k>>1),false);
reverse(right.begin(),right.end());
ll ans=INF;
for(int i=0;i<n;i++){
ans=min(ans,left[i]+right[i]);
}
cout<<(ans==INF?points[0].second:ans)<<endl;
return 0;
}