传送门:HDU6136
题意:n个人在圆形上运动,他们都有一定的速度和初始位置,当两个人相遇的时候编号较小的就会出局,当场上剩下最后一个人的时候游戏结束,问多长时间游戏会结束。
思路:官方题解:
我用的是解法一。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> P;
const int MAXN = 100010;
struct node{
int d, w, v;
bool operator < (node a) const
{
return d < a.d;
}
}p[MAXN];
int pre[MAXN], nxt[MAXN], book[MAXN];
struct ac{
int id1, id2;
double t;
ac(int _id1 = 0, int _id2 = 0, double _t = 0) : id1(_id1), id2(_id2), t(_t) {}
bool operator < (ac a) const
{
return t > a.t;
}
};
int L;
double calc(int a, int b)
{
int v = p[a].v - p[b].v;
int d = p[b].d - p[a].d;
if(d < 0) d += L;
if(v < 0) d = L - d, v = -v;
if(v == 0) return inf;
return d * 1.0 / v;
}
priority_queue<ac> q;
void del(int id)
{
book[id] = 1;
q.push(ac(pre[id], nxt[id], calc(pre[id], nxt[id])));
nxt[pre[id]] = nxt[id];
pre[nxt[id]] = pre[id];
}
int main()
{
int T;
cin >> T;
while(T--)
{
int n;
memset(book, 0, sizeof book);
scanf("%d %d", &n, &L);
for(int i = 0; i < n; i++)
scanf("%d", &p[i].d), p[i].w = i;
for(int i = 0; i < n; i++)
scanf("%d", &p[i].v);
sort(p, p + n);
for(int i = 0; i < n; i++)
{
nxt[i] = (i + 1) % n;
pre[i] = (i - 1 + n) % n;
q.push(ac(i, nxt[i], calc(i, nxt[i])));
}
ac tmp;
while(!q.empty())
{
tmp = q.top(); q.pop();
if(book[tmp.id1] || book[tmp.id2]) continue;
if(n == 2) break;
n--;
if(p[tmp.id1].w > p[tmp.id2].w) del(tmp.id2);
else del(tmp.id1);
}
while(!q.empty()) q.pop();
if(tmp.id2 < tmp.id1) swap(tmp.id1, tmp.id2);
int fm = p[tmp.id1].v - p[tmp.id2].v;
int fz = p[tmp.id2].d - p[tmp.id1].d;
if(fz < 0) fz += L;
if(fm < 0) fz = L - fz, fm = -fm;
printf("%d/%d\n", fz / __gcd(fz, fm), fm / __gcd(fz, fm));
}
return 0;
}
第二种线性解法的思路和栈的运用都很巧妙。