2018多校第3场 G题 && HDU6325 Problem G. Interstellar Travel

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/computer_user/article/details/81297808

题目链接:G-Interstellar Travel

 

思路分析:因为坐标相同的点只能选一个(比赛没看到这条件,浪费了2个半小时)...所以当然选择编号最小的最优

从凸包上面走会更优,所以答案的解肯定包括起点,终点,凸包拐点。

假如凸包一条边上有多点共线,那么就要看边上的点编号是否比边的终点编号小,是的话放到答案里解会更优。因为题目求的是字典序最小。

 

代码如下:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

typedef long long LL;
struct Point{
   LL x,y;
   int idx;
   Point(){}
   Point(LL x, LL y, int idx):x(x),y(y),idx(idx){}
   bool operator <(const Point &rhs) const {
      if (x != rhs.x) return x<rhs.x;
      if (y != rhs.y) return y>rhs.y;
      return idx < rhs.idx;
   }
};

typedef Point Vector;
Vector operator +(Vector A, Vector B) {return Vector(A.x+B.x,A.y+B.y,0); }
Vector operator -(Vector A, Vector B) {return Vector(A.x-B.x,A.y-B.y,0); }
LL Cross(Vector A, Vector B) {return A.x*B.y-A.y*B.x;}

const int maxn = 2e5+10;
Point p[maxn],ch[maxn];
bool vis[maxn];
int ans[maxn];
LL x,y;
int n,m;

int ConvexHull(Point *p, int n, Point *ch){
    int m = 0;
    for (int i=0; i<n; ++i) {
        if (i>0 && p[i].x == p[i-1].x) continue;
        while (m>1 && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]) > 0) m--;
        ch[m++] = p[i];
    }
    return m;
}

int main(){
    int T; scanf("%d",&T);
    while (T--) {
       scanf("%d",&n);
       for (int i=0; i<n; ++i) {
          scanf("%lld%lld",&x,&y);
          p[i] = Point(x,y,i+1);
       }
       sort(p,p+n);
       m = ConvexHull(p,n,ch);

       memset(vis,0,sizeof(vis));
       vis[0] = vis[m-1] = 1; ans[0] = 1; ans[m-1] = n;
       for (int i=1; i<m-1; ++i) if (Cross(ch[i]-ch[i-1],ch[i+1]-ch[i-1]) != 0) vis[i] = 1;

       for (int i=m-2; i>0; i--) {
           if (vis[i]) ans[i] = ch[i].idx;
           else ans[i] = min(ans[i+1],ch[i].idx);
       }

       for (int i=0; i<m-1; ++i) if (ans[i] == ch[i].idx) printf("%d ",ans[i]);
       printf("%d\n",n);
    }
    return 0;
}

 

阅读更多

没有更多推荐了,返回首页