zoukankan      html  css  js  c++  java
  • Problem G. Interstellar Travel

     PS:首先这样的路线是按照顺时针走的,那么两个点的叉积必定是负数,负数最小,则代表面积最大,因为叉积还可以表示成三角形的面积,想象一下,路线与x轴围成的面积最大,那么路线应该绕着上凸包。重点来了,字典序最小。因为凸包的拐点、起点、终点是必须要的,那么为了最小化字典序,在同一条边上共线的点中(除了这条边的起点和终点)选一个编号最小的点作降落点M,然后从M点开始,选某个字典序最小的递增序列。比如 3 1 4 2 7,选3 1 2 7,M点是编号为1的点。

    //#include<bits/stdc++.h>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<bitset>
    #include<vector>
    #include<queue>
    #include<map>
    #include<string>
    #include<stack>
    #define ll long long
    #define P pair<int, int>
    #define PP pair<int,pair<int, int>>
    #define pb push_back
    #define pp pop_back
    #define lson root << 1
    #define INF (int)2e9 + 7
    #define rson root << 1 | 1
    #define LINF (unsigned long long int)1e18
    #define mem(arry, in) memset(arry, in, sizeof(arry))
    using namespace std;
    
    const int N = 200005;
    
    int n, T, ans[N];
    bool use[N];
    struct node { int x, y, id; } a[N], p[N];
    
    bool cmp(const node& aa, const node& bb) {
        if(aa.x != bb.x) return aa.x < bb.x;
        if(aa.y != bb.y) return aa.y > bb.y;
        return aa.id < bb.id;
    }
    
    ll Cross(const node& aa, const node& bb, const node& cc) {
        return 1ll * (bb.y - aa.y) * (cc.x - bb.x) - 1ll * (bb.x - aa.x) * (cc.y - bb.y);
    }
    
    int main()
    {
        cin >> T;
        while(T--) {
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) scanf("%d %d", &a[i].x, &a[i].y), a[i].id = i;
            sort(a + 1, a + n + 1, cmp);
            int t = 0;
            for(int i = 1; i <= n; i++) {
                if(i > 1 && a[i].x == a[i - 1].x) continue;
                while(t > 1 && Cross(p[t - 1], p[t], a[i]) < 0) t--;
                p[++t] = a[i];
            }
    
            mem(use, 0);
            use[1] = use[t] = 1;
            for(int i = 2; i < t; i++) {
                if(Cross(p[i - 1], p[i], p[i + 1]) != 0) use[i] = 1;
            }
    
            for(int i = t; i; i--) {
                if(use[i]) ans[i] = p[i].id;
                else ans[i] = min(ans[i + 1], p[i].id);
            }
            for(int i = 1; i < t; i++) if(ans[i] == p[i].id) printf("%d ", ans[i]);
            printf("%d
    ", ans[t]);
        }
        return 0;
    }
  • 相关阅读:
    c++
    zjoi 力
    poj 3415
    [SDOI2014]旅行
    模板测试
    [WC2006]水管局长
    HDU5730
    [NOI2014]魔法森林
    [NOI2012]骑行川藏(未完成)
    [NOI2012]随机数生成器
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9403756.html
Copyright © 2011-2022 走看看