您的位置:首页 > 其它

poj 2274 The Race 最小堆

2016-06-15 23:45 281 查看

题目链接

题目大意:

给n个小车, 每个小车有一个初始位置x和初始速度v, 保证x1 < x2..... <xn。 0<v<100。

然后问你一共会发生多少次超车, 以及前10000次超车分别是哪两辆车, 按超车的时间顺序给出。

思路:

第一问显然就是一个逆序数, 因为v<100, 所以暴力统计就可以了。

第二问, 我们通过观察可以得出一个性质, 超车总是先发生在相邻的两辆车。

比如a, b, c三个车, 如果他们的速度是va > vc > vb, 那么超车肯定是a超过b, 然后才能超过c。 a不可能直接不通过b就超过c。

有了这个性质, 我们可以先将所有相邻的可能发生的超车情况放入一个优先队列。 队列里的元素有4个值, 超车的时间, 超车发生的坐标, 超车的两辆车的编号。

然后初始的时候记录一下每个车前面的车的坐标以及后面的坐标。 初始就是i-1和i+1。

然后如果发生超车, 比如初始是 1, 2, 3, 4。 然后2超过3, 变成1, 3, 2, 4。 每辆车的前后坐标也要改变。 初始pre[2] = 1, nxt[2] = 3,超车之后变成pre[2] = 3, nxt[2] = 4。大概就是这样。 同时1, 3, 4也都会发生改变。

然后每次超车之后, 在将新的可能发生的超车加入队列。 然后这么不断循环。直到队列空或者10000个。

还有一种就是 a, b, c 三个车, va > vb > vc, 然后初始将a超过b, b超过c的情况放入了队列, 这时候b超过了c, 然后将a超过c的情况放入队列。然后a超过c, 再次将a超过b的情况放入队列。如果不判断一下的话就会将a超过b的情况计算两次。 判断的方法, 我是这样的。 比如两辆车a,b。 看nxt[a]是否等于b以及pre[b] 是否等于a, 如果不等于直接continue。

具体的可以看看代码自己想一下... 真是写了好久。

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <complex>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define mem(a) memset(a, 0, sizeof(a))
#define fi first
#define se second
typedef pair<int, int> pll;
const double eps = 1e-8;
const int maxn = 250005;
int cnt[100], pre[maxn], nxt[maxn];
double v[maxn], x[maxn];
struct node
{
double t, pos;
int car1, car2;
node(){}
node(double t, double pos, int car1, int car2):t(t), pos(pos), car1(car1), car2(car2){}
bool operator < (node a) const
{
if(fabs(t - a.t)<eps) {
return pos > a.pos;
}
return t > a.t;
}
};
vector <pll> ans;
int main()
{
int n;
while(cin>>n) {
priority_queue <node> q;
ans.clear();
mem(cnt);
mem(pre);
mem(nxt);
int sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%lf%lf", &x[i], &v[i]);
nxt[i] = i+1;
pre[i] = i-1;
cnt[(int)v[i]]++;
for(int j = v[i]+1; j < 100; j++) {
sum += cnt[j];
sum %= 1000000;
}
}
for(int i = 1; i < n; i++) {
if(v[i] > v[i+1]) {
double t = 1.0*(x[i+1]-x[i])/(v[i]-v[i+1]);
q.push(node(t, t*v[i]+x[i], i, i+1));
}
}
int num = 10000;
while(num && !q.empty()) {
node tmp = q.top(); q.pop();
int fi = tmp.car1, se = tmp.car2;
if(nxt[fi] != se || pre[se] != fi)
continue;
ans.pb(mk(fi, se));
nxt[fi] = nxt[se];
pre[se] = pre[fi];
nxt[se] = fi;
pre[fi] = se;
nxt[pre[se]] = se;
pre[nxt[fi]] = fi;
if(pre[se] && v[pre[se]] > v[se]) {
double t = (tmp.pos - v[pre[se]]*tmp.t-x[pre[se]])/(v[pre[se]] - v[se]);
q.push(node(tmp.t + t, tmp.pos + v[se]*t, pre[se], se));
}
if(nxt[fi] != n+1 && v[fi] > v[nxt[fi]]) {
double t = 1.0*(x[nxt[fi]] + v[nxt[fi]]*tmp.t - tmp.pos)/(v[fi] - v[nxt[fi]]);
q.push(node(tmp.t+t, tmp.pos + v[fi]*t, fi, nxt[fi]));
}
num--;
}
cout<<sum<<endl;
for(int i = 0; i < ans.size(); i++) {
printf("%d %d\n", ans[i].fi, ans[i].se);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: