zoukankan      html  css  js  c++  java
  • 旋转卡壳

    题解:

    大致就是先求出凸包

    然后有一个性质就是我们枚举每条边

    然后凸包上的点到边的距离是单峰函数(刚开始傻逼的写了点对点)

    于是可以two-point-two

    为什么是对的呢

    因为对于最远点对

    我们取一条平行于边的直线,那这条边到那个点的距离就是最远距离

    所以这样就是对的

    另外我发现求凸包的代码需要判重。。

    不过网上好多代码都不判重。。这样有重复点的话是错的

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    using namespace std;
    #define rint register int
    #define IL inline
    #define ll long long
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    const int N=4e5;
    struct point{
      int a,b,r;
      bool operator ==(point o)
      {
        return a==o.a&&b==o.b;
      }
      IL void jsr()
      {
        r=atan2(b,a);
      }
      point operator -(point o)
      {
        return (point){a-o.a,b-o.b};
      }
      point operator +(point o)
      {
        return (point){a+o.a,b+o.b};
      }
      int operator *(point o)
      {
        return a*o.a+b*o.b;
      } 
      int operator ^(point o)
      {
        return a*o.b-b*o.a;
      }
    }p[N],q[N];
    struct line{
      point a,b;
    };
    IL int dis(point x,point y)
    {
      return (x.a-y.a)*(x.a-y.a)+(x.b-y.b)*(x.b-y.b);
    }
    int lenth(point x)
    {
      return x.a*x.a+x.b*x.b;
    }
    IL int dis(point x,point y,point z)
    {
      if ((y-x)*(z-x)<=0) return dis(x,z);
      if ((x-y)*(z-y)<=0) return dis(y,z);
      int l=1ll*((y-x)^(z-x))*((y-x)^(z-x))/lenth(y-x);
      return l;
    }
    IL bool cmp(point x,point y)
    {
      return x.a<y.a||(x.a==y.a&&x.b<y.b);
    }
    IL bool pd(line x,point y)
    {
      return (x.b^(y-x.a))<0;
    }
    int t,n;
    void push(point x)
    {
      while (1<t&&pd((line){q[t-1],q[t]-q[t-1]},x)) t--;
      q[++t]=x;
    }
    template<class T>void maxa(T &x,T y) {if (x<y)x=y;}
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false); 
      cin>>n;
      rep(i,1,n)
      {
        int x,y;
        cin>>x>>y;
        p[i]=(point){x,y};
        p[i].jsr();
      }
      sort(p+1,p+n+1,cmp);
      int m=0;
      rep(i,1,n)
        if (i==1||!(p[i]==p[i-1]))
          p[++m]=p[i];
      n=m;
      t=1;
      q[0]=q[t]=p[1];
      rep(i,2,n) 
        push(p[i]);
      dep(i,n-1,1) 
        push(p[i]);
      int k2=1;
      int ans=0;
     /* rep(i,1,t)
      {
        while (k2<t&&dis(q[i],q[k2+1])>dis(q[i],q[k2])) k2++;
        maxa(ans,dis(q[i],q[k2]));
      }*/
      rep(i,t+1,2*t) q[i]=q[i-t];
      rep(i,1,t)
      {
        while (k2<2*t&&dis(q[i],q[i+1],q[k2])<=dis(q[i],q[i+1],q[k2+1])) k2++;
        maxa(ans,dis(q[i],q[k2]));
        maxa(ans,dis(q[i+1],q[k2])); 
      }
      printf("%d",ans);
      return 0;
    }
  • 相关阅读:
    UIView与CALayer的区别,很详细
    iOS开发之启动动画(动态欢迎界面,非静态Default)
    js前端验证时间大小
    C#联通新版验证码识别的实现
    C#打印100以内质数
    SQL竖表转横表 / 横表转竖表
    不用中间变量交换两个变量的值
    单例模式
    C#递归遍历指定目录下文件和文件夹
    冒泡排序
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/10206348.html
Copyright © 2011-2022 走看看