BZOJ2739 : 最远点

把环倍长,设$w(i,j)$表示对于$i$,决策$j$的价值,如果$j$在$[i,i+n]$,那么$w(i,j)=dis(i,j)$,否则$w(i,j)=-dis(i,j)$。

则$w$满足四边形不等式,最优决策满足完全单调性,分治求解即可。

时间复杂度$O(n\log n)$。

 

#include<cstdio>
#define N 500010
int T,n,i,f[N];struct P{int x,y,p;}a[N<<1];
inline void read(int&a){
  char c;bool f=0;a=0;
  while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
  if(c!='-')a=c-'0';else f=1;
  while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
  if(f)a=-a;
}
inline bool cmp(int i,int j,int k){
  long long x=1LL*(a[i].x-a[j].x)*(a[i].x-a[j].x)+1LL*(a[i].y-a[j].y)*(a[i].y-a[j].y),
            y=1LL*(a[i].x-a[k].x)*(a[i].x-a[k].x)+1LL*(a[i].y-a[k].y)*(a[i].y-a[k].y);
  if(j<i||j>i+n)x=-x;
  if(k<i||k>i+n)y=-y;
  return x==y?a[j].p>a[k].p:x<y;
}
void solve(int l,int r,int dl,int dr){
  int mid=(l+r)>>1,dm=dl;
  for(int i=dl+1;i<=dr;i++)if(cmp(mid,dm,i))dm=i;
  f[mid]=a[dm].p;
  if(l<mid)solve(l,mid-1,dl,dm);
  if(r>mid)solve(mid+1,r,dm,dr);
}
int main(){
  read(T);
  while(T--){
    read(n);
    for(i=1;i<=n;i++)read(a[i].x),read(a[i].y),a[i].p=i,a[n+i]=a[i];
    solve(1,n,1,n+n);
    for(i=1;i<=n;i++)printf("%d\n",f[i]);
  }
  return 0;
}

  

你可能感兴趣的:(BZOJ2739 : 最远点)