【多校2018#3】HDU6325 Problem G. Interstellar Travel
题面在这里
两点之间代价就是叉积啊……
考虑几何意义,就是让围成的面积最大(负值)
那么就是一个上凸壳,直接做就好了
然而要字典序最小,考虑使凸包产生多种方案一定是三点共线,判一下即可
最后还是被重复点坑死了
示例程序:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*l=buf,*r=buf; return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++; } inline int red(){ int res=0,f=1;char ch=nc(); while (ch<'0'||'9'<ch) {if (ch=='-') f=-f;ch=nc();} while ('0'<=ch&&ch<='9') res=res*10+ch-48,ch=nc(); return res*f; }
const int maxn=200005; int tst,n,stk[maxn],len,id[maxn]; struct point{ ll x,y;int id; point () {} point (ll _x,ll _y) :x(_x),y(_y) {} bool operator<(const point&b)const {return x<b.x||x==b.x&&y<b.y;} }a[maxn]; typedef point vec; inline vec operator-(const point&a,const point&b) {return vec(a.x-b.x,a.y-b.y);} inline ll cross(const vec&a,const vec&b) {return a.x*b.y-a.y*b.x;} int main(){ tst=red(); while (tst--){ n=red(); for (int i=1;i<=n;i++) a[i].x=red(),a[i].y=red(),a[i].id=i; sort(a+1,a+1+n); len=0; for (int i=1;i<=n;i++){ while (len>1){ ll c=cross(a[stk[len]]-a[stk[len-1]],a[i]-a[stk[len-1]]); if (c>0||c==0&&a[stk[len]].id>a[i].id) len--;else break; } if (len==0||a[i].x!=a[stk[len]].x) stk[++len]=i; } for (int i=1;i<=len;i++) if (i<len) printf("%d ",a[stk[i]].id);else printf("%d\n",a[stk[i]].id); } }
|