【BZOJ2739】最远点

Description

  给你一个N个点的凸多边形,求离每一个点最远的点。
Input

  本题有多组数据,第一行一个数T,表示数据组数。
  每组数据第一行一个数N,表示凸多边形点的个数,接下来N对数,依次表示1~N这N个点的坐标,按照逆时针给出。
Output

  对于每组数据输出N个数,第i个数表示离第i个点最远的点的编号,如果有多个最远点,输出编号最小的。
Sample Input

1

4

0 0

1 0

1 1

0 1

Sample Output

3

4

1

2

HINT

数据规模和约定

  坐标的绝对值在1e9以内;

  任意点对距离数值的平方不会超过long long;

  令S为每组数据凸多边形点数之和;

  对于20%的数据,S<=2000;

  对于50%的数据,S<=50000;

  对于100%的数据,S<=500000;

  数据有梯度。

Source

Claris推荐的神题系列.
感受了一下发现决策是单调的,不过没打表也没证明.
证明可以用四边形不等式,这个我不会,不过可以参考Claris的题解.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 500010
#define GET (ch>='0'&&ch<='9')
#define LL long long
using namespace std;
int T,n,f[MAXN];
struct node {   int x,y,id; }s[MAXN<<1];
LL dis(node a,node b)   {   return 1ll*(a.x-b.x)*(a.x-b.x)+1ll*(a.y-b.y)*(a.y-b.y); }
void in(int &x)
{
    char ch=getchar();x=0;int flag=1;
    while (!GET)    flag=ch=='-'?-1:1,ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();x*=flag;
}
bool comp(int now,int pos1,int pos2)
{
    LL t1=dis(s[now],s[pos1]),t2=dis(s[now],s[pos2]);
    if (pos1<now||pos1>now+n)   t1=-t1;
    if (pos2<now||pos2>now+n)   t2=-t2;
    return t1!=t2?t1<t2:s[pos1].id>s[pos2].id;
}
void solve(int l,int r,int L,int R)//l,r 当前状态点 L,R 决策点 
{
    if (l>r)    return;
    int mid=(l+r)>>1,Mid=L;
    for (int i=L;i<=R;i++)  if (comp(mid,Mid,i))    Mid=i;
    f[mid]=s[Mid].id;
    solve(l,mid-1,L,Mid);solve(mid+1,r,Mid,R);
}
int main()
{
    for (in(T);T;T--)
    {
        in(n);
        for (int i=1;i<=n;i++)  in(s[i].x),in(s[i].y),s[i].id=i,s[i+n]=s[i];
        solve(1,n,1,n<<1);
        for (int i=1;i<=n;i++)  printf("%d\n",f[i]);
    }
}

你可能感兴趣的:(dp)