【题解】【HDU6136】2017多校第8场 炮艇大赛之正式赛

用了个比较显然的做法

思路:

第一次相遇的必是两个环上相邻的两个人

正确性显然

第一个出局的人不会对后续的状态有任何影响

同上,显然

于是我们就把问题的规模从n缩小到了n-1

对于缩小后的子问题,我们也能用同样的方法

但同时,原本不相邻的现在相邻了

于是我们需要一种方法,来快速取得最小值,并支持插入

很显然,这就是堆

搞定了……

时间复杂度(O(nlogn))

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

const int N=100010;

struct note {
    int x,y;
    note(int u=0,int v=1){
        x=u;
        y=v;
    }
};

bool operator < (const note &x,const note &y) {
    return x.x/(double)x.y>y.x/(double)y.y;
}

note operator + (const note &x,const note &y) {
    return note(x.x*y.y+y.x*x.y,x.y*y.y);
}

note operator - (const note &x,const note &y) {
    return note(x.x*y.y-y.x*x.y,x.y*y.y);
}

struct data {
    int x,y;
    note t;
};

bool operator < (const data &a,const data &b) {
    return a.t<b.t;
}

struct boat {
    int d;
    int v;
    int val;
};

bool operator < (const boat &x,const boat &y) {
    return x.d<y.d;
}

int n,L;
note ans;
data e;
boat a[N];
priority_queue<data> q;
bool out[N];

note get(boat x,boat y) {
    if (x.d<y.d) {
        if (x.v<y.v) {
            return note(L-y.d+x.d,y.v-x.v);
        } else {
            return note(y.d-x.d,x.v-y.v);
        }
    } else {
        if (x.v<y.v) {
            return note(x.d-y.d,y.v-x.v);
        } else {
            return note(L-x.d+y.d,x.v-y.v);
        }
    }
}

inline int gcd(int x,int y) {
    while(y^=x^=y^=x%=y);
    return x;
}

inline bool comp(const boat &x,const boat &y) {
    return x.d<y.d;
}

int main() {
    scanf("%d %d",&n,&L);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i].d);
        a[i].val=i;
    }
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i].v);
    }
    sort(a+1,a+n+1,comp);
    e.x=n;
    e.y=1;
    e.t=get(a[1],a[n]);
    q.push(e);
    for(int i=1;i<n;i++) {
        e.x=i;
        e.y=i+1;
        e.t=get(a[i],a[i+1]);
        q.push(e);
    }
    int num=n;
    while(q.size()>1) {
        e=q.top();
        q.pop();
        if (out[a[e.x].val]||out[a[e.y].val]) {
            continue;
        }
        if (num==2) {
            break;
        }
        if (a[e.x].val<a[e.y].val) {
            out[a[e.x].val]=1;
            while(out[a[e.x].val]) {
                e.x--;
                if (e.x==0) {
                    e.x=n;
                }
            }
        } else {
            out[a[e.y].val]=1;
            while(out[a[e.y].val]) {
                e.y++;
                if (e.y>n) {
                    e.y=1;
                }
            }
        }
        num--;
        e.t=get(a[e.x],a[e.y]);
        q.push(e);
    }
    data k=q.top();
    ans=k.t;
    int o=gcd(ans.x,ans.y);
    printf("%d/%d",ans.x/o,ans.y/o);
    return 0;
}

原文地址:https://www.cnblogs.com/tt66ea-blog/p/11305583.html