[bzoj3210]花神的浇花集会

来自FallDream的博客,未经允许,请勿转载,谢谢。


 

在花老师的指导下,每周4都有一个集会活动,俗称“浇水”活动。

具体浇水活动详情请见BZOJ3153

但这不是重点

花神出了好多题,每道题都有两个参考系数:代码难度和算法难度

花神为了准备浇花集会的题,必须找一道尽量适合所有人的题

现在花神知道每个人的代码能力x和算法能力y,一道题(代码难度X算法难度Y)对这个人的不适合度为    Max ( abs ( X – x ) , abs ( Y – y ) )

也就是说无论太难还是太简单都会导致题目不适合做(如果全按花神本人能力设题,绝对的全场爆0的节奏,太简单,则体现不出花神的实力)

当然不是每次都如花神所愿,不一定有一道题适合所有人,所以要使所有人的不合适度总和尽可能低

花神出了100001*100001道题,每道题的代码难度和算法难度都为0,1,2,3,……,100000

n,xi,yi<=10^5   0.1s

 

求一个点,使得它到所有点的切尔雪夫距离之和最小

因为切尔雪夫距离等于把所有点(xi,yi)变成(xi+yi,yi-xi)之后的曼哈顿距离的一半,所以两个坐标求一个中位数就行了。如果中位数奇偶性不同可以暴力一下。

当然,很容易发现这是一个单峰函数,所以可以爬山

#include<iostream>
#include<cstdio>
#include<algorithm>
#define getchar() ((S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T))?EOF:*S++)
#define MN 100000
char B[1<<15],*S=B,*T=B;
using namespace std;
inline int read()
{
    int 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 * 10 + ch - '0';ch = getchar();}
    return x * f;
}
struct P{int x,y;}p[MN+5];
bool cmpx(P x,P y){return x.x<y.x;}
bool cmpy(P x,P y){return x.y<y.y;}
int n;
long long ans=0;
inline int abs(int x){return x<0?-x:x;}
inline long long calc(int x,int y)
{
    long long sum=0;
    for(register int i=1;i<=n;++i) sum+=abs(p[i].x-x)+abs(p[i].y-y);
    return sum;    
}
int main()
{
    n=read();int m=(n+1)>>1,x,y;
    for(register int i=1;i<=n;++i)
    {
        int x=read(),y=read();
        p[i]=(P){x+y,y-x};    
    }
    nth_element(p+1,p+m,p+n+1,cmpx);x=p[m].x;
    nth_element(p+1,p+m,p+n+1,cmpy);y=p[m].y; 
    if((x&1)==(y&1)) return 0*printf("%lld",calc(x,y)>>1);
    else
    {
        ans=(1LL<<60);
        for(register int i=-1;i<=1;i+=2)
            ans=min(ans,min(calc(x+i,y),calc(x,y+i)));
    }
    printf("%lld\n",ans>>1);
    return 0;
}
正解
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define MN 100000
using namespace std;
inline int read()
{
    int 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 * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int n;ll ans=0;
const int dis[8][2]={{1,0},{0,1},{0,-1},{-1,0},{1,1},{-1,-1},{-1,1},{1,-1}};
struct P{int x,y;}p[MN+5];
bool cmpx(P x,P y){return x.x<y.x;}
bool cmpy(P x,P y){return x.y<y.y;}
inline int abs(int x){return x<0?-x:x;}
inline ll calc(int x,int y)
{
    if(x<0||y<0||x>MN||y>MN) return (1LL<<60);
    ll sum=0;
    for(int i=1;i<=n;++i) sum+=max(abs(p[i].x-x),abs(p[i].y-y));
    return sum;
}

int main()
{
    n=read();int m=(n+1)>>1,x,y;
    for(int i=1;i<=n;++i) p[i].x=read(),p[i].y=read();    
    nth_element(p+1,p+m,p+n+1,cmpx);x=p[m].x;
    nth_element(p+1,p+m,p+n+1,cmpy);y=p[m].y;
    ans=calc(x,y);
    for(int l=5000;l;l>>=1)
    {
        for(int flag=1;flag;)
        {
            flag=0;
            for(int i=0;i<8;++i)
            {
                int nx=x+dis[i][0]*l,ny=y+dis[i][1]*l;
                ll now=calc(nx,ny);
                if(now<ans)
                {
                    x=nx;y=ny;ans=now;
                    flag=1;
                    break;    
                }
            }
        }    
    }
    printf("%lld\n",ans);
    return 0;
}
爬山
posted @ 2017-05-26 17:19  FallDream  阅读(269)  评论(0编辑  收藏  举报