http://codeforces.com/gym/100792/problem/G
既然刚才写了平面几何技巧,干脆来个二连发。
看n=20w和这个题意感觉应该是经典问题,看了半个小时一点想法都没有_(:зゝ∠)_然后被阳神训斥了_(:зゝ∠)_然后一下子就懂了_(:зゝ∠)_
题意:定义两点距离为(√2−1)*max(abs(x[i]-x[j]),abs(y[i]-y[j]))+min(abs(x[i]-x[j]),abs(y[i]-y[j]))
然后求平面最远点对。
平面最远点对不是个经典nlog问题吗,看了一下这个和欧几里得距离不一样不会来_(:зゝ∠)_然后想了一下旋转45。,发现并没有什么卵用,因为这个东西本来就是有45。的路径的然后我整个人就懵逼了_(:зゝ∠)_
然后阳神就过来训斥了我_(:зゝ∠)_你这个东西不是O(n*8)的SB东西吗_(:зゝ∠)_
因为两点之间的距离中一共有3个不同的max或者min(abs也算作max(k,-k)),也就是说一共也就8种情况,因为两点之间的距离一定是8种情况里最大的一种,然后我们8种情况分别记录当前的最优点就行了。
怕没听懂还是写一下8种情况吧:
1、dis=(√2−1))*(x[i]-x[j])+y[i]-y[j];
2、dis=(√2−1))*(x[i]-x[j])+y[j]-y[i];
3、dis=(√2−1))*(x[j]-x[i])+y[i]-y[j];
4、dis=(√2−1))*(x[j]-x[i])+y[j]-y[i];
5、dis=(√2−1))*(y[i]-y[j])+x[i]-x[j];
6、dis=(√2−1))*(y[i]-y[j])+x[j]-x[i];
7、dis=(√2−1))*(y[j]-y[i])+x[i]-x[j];
8、dis=(√2−1))*(y[j]-y[i])+x[j]-x[i];
这样就很清晰了_(:зゝ∠)_单独对于每一种情况,在x[i]、y[i]相同的情况下,某个work(x[j],y[j])一定与dis有单调性,我们只要按照这个单调性维护最优点就行了_(:зゝ∠)_总复杂度空间O(1),时间O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <span style= "font-family:comic sans ms,cursive;" ># include <cstdio> # include <cmath> using namespace std; double t=sqrt( 2 )- 1 ; struct point{ int x,y,k; }p[ 200005 ],P[ 8 ]; int n,X,Y; double ans; double a[ 8 ]={t, 1 ,t, 1 ,-t,- 1 ,-t,- 1 }; double b[ 8 ]={ 1 ,t,- 1 ,-t, 1 ,t,- 1 ,-t}; int main(){ scanf( "%d" ,&n); for ( int i= 1 ;i<=n;i++)scanf( "%d%d" ,&p[i].x,&p[i].y),p[i].k=i; for ( int i= 0 ;i< 8 ;i++)P[i]=p[ 1 ]; ans=- 1 ; for ( int i= 2 ;i<=n;i++){ for ( int j= 0 ;j< 8 ;j++){ double s=(P[j].y-p[i].y)*b[j]+(P[j].x-p[i].x)*a[j]; if (s>ans){ X=P[j].k; Y=p[i].k; ans=s; } } for ( int j= 0 ;j< 8 ;j++) if (p[i].x*a[j]+p[i].y*b[j]>P[j].x*a[j]+P[j].y*b[j])P[j]=p[i]; } printf( "%d %d\n" ,X,Y); }</span> |
一边读一边做可以做到空间O(1)不想改了_(:зゝ∠)_