根据旋转卡壳,当逆时针遍历点时,相应的最远点也逆时针转动,满足决策单调性。于是倍长成链,分治优化DP即可,复杂度O(nlogn)。
1 #include<cstdio> 2 #include<algorithm> 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 4 typedef long long ll; 5 using namespace std; 6 7 const int N=1000010,inf=1e9; 8 9 int n,T,ans[N]; 10 struct P{ int x,y,id; }a[N]; 11 ll sqr(ll x){ return x*x; } 12 ll dis(P a,P b){ return sqr(a.x-b.x)+sqr(a.y-b.y); } 13 14 bool chk(int i,int k1,int k2){ 15 if (k1<i || k1>i+n) return 0; 16 if (k2<i || k2>i+n) return 1; 17 ll d1=dis(a[i],a[k1]),d2=dis(a[i],a[k2]); 18 return d1==d2 ? a[k1].id<a[k2].id : d1>d2; 19 } 20 21 void solve(int l,int r,int L,int R){ 22 if (l>r) return; 23 int mid=(l+r)>>1,pos=0; 24 rep(i,L,R) if (chk(mid,i,pos)) pos=i; 25 ans[mid]=pos>n ? pos-n : pos; 26 solve(l,mid-1,L,pos); solve(mid+1,r,pos,R); 27 } 28 29 int main(){ 30 freopen("bzoj2739.in","r",stdin); 31 freopen("bzoj2739.out","w",stdout); 32 for (scanf("%d",&T); T--; ){ 33 scanf("%d",&n); 34 rep(i,1,n) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i,a[n+i]=a[i]; 35 solve(1,n,1,n<<1); 36 rep(i,1,n) printf("%d ",ans[i]); 37 } 38 return 0; 39 }