题目链接

题目大意:

给n个小车, 每个小车有一个初始位置x和初始速度v, 保证x1 思路:

第一问显然就是一个逆序数, 因为v
第二问, 我们通过观察可以得出一个性质, 超车总是先发生在相邻的两辆车。
比如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;
}

poj 2274 The Race 最小堆的更多相关文章

  1. 最小堆的维护,POJ(2051)

    题目链接:http://poj.org/problem?id=2051 ///维持最小堆(优先队列)POJ2051 #include <iostream> #include <str ...

  2. 《徐徐道来话Java》:PriorityQueue和最小堆

    在讲解PriorityQueue之前,需要先熟悉一个有序数据结构:最小堆. 最小堆是一种经过排序的完全二叉树,其中任一非终端节点数值均不大于其左孩子和右孩子节点的值. 可以得出结论,如果一棵二叉树满足 ...

  3. c++/java/python priority_que实现最大堆和最小堆

    #include<iostream>#include<vector>#include<math.h>#include<string>#include&l ...

  4. 最大堆 最小堆 解决TOPK问题

    堆:实质是一颗完全二叉树,最大堆的特点:父节点值均大于子节点:最小堆的父节点值均小于子节点: 一般使用连续内存存储堆内的值,因而可以根据当前节点的索引值推断子节点的索引值: 节点i的父节点为(i-1) ...

  5. Python3实现最小堆建堆算法

    今天看Python CookBook中关于“求list中最大(最小)的N个元素”的内容,介绍了直接使用python的heapq模块的nlargest和nsmallest函数的解决方式,记得学习数据结构 ...

  6. Google 面试题:Java实现用最大堆和最小堆查找中位数 Find median with min heap and max heap in Java

    Google面试题 股市上一个股票的价格从开市开始是不停的变化的,需要开发一个系统,给定一个股票,它能实时显示从开市到当前时间的这个股票的价格的中位数(中值). SOLUTION 1: 1.维持两个h ...

  7. 【数据结构】通用的最小堆(最大堆)D-ary Heap

    听说有一种最小(大)堆,不限于是完全二叉树,而是完全D叉树,名为D-ary Heap(http://en.wikipedia.org/wiki/D-ary_heap).D可以是1,2,3,4,100, ...

  8. 使用最小堆来完成k路归并 6.5-8

    感谢:http://blog.csdn.net/mishifangxiangdefeng/article/details/7668486 声明:供自己学习之便而收集整理 题目:请给出一个时间为O(nl ...

  9. My集合框架第五弹 最小堆

    二叉堆(以最小堆为例),其具有结构性质和堆序性质结构性质: 堆是一棵完全的二叉树,一颗高为h的完全二叉树有2^h到2^h-1个节点,高度为log N            而且该结构可以很容易的使用数 ...

随机推荐

  1. C# VS 面向对象基础(一)

    面向对象(Object Oriented,OO)的相关知识学习了很多了,这篇博客我从C#实现面向对象的理论来做个初步的总结. 在这篇博客中,我通过一个例子讲述了,面向对象中,类,类的实例化,构造方法, ...

  2. 在 WinForm 中打开页面采用POST方式传参http。可以多个参数传递,返回json字符串

    //调用方法 Dictionary<string, string> postData = new Dictionary<string, string>(); postData. ...

  3. Javascript 多物体运动——逐行分析代码,让你轻松了解运动的原理

    我们先来看下之前的运动的代码,是否支持多物体运动,会出现怎么样的问题. <style type="text/css"> div { width: 100px; heig ...

  4. linux dd命令

    dd 是 Linux/UNIX 下的一个非常有用的命令,作用是用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. 1. 命令简介 dd 的主要选项: 指定数字的地方若以下列字符结尾乘以相应的数 ...

  5. Delphi 实现无窗口移动(发WM_NCHITTEST消息计算,然后再发WM_SYSCOMMAND消息,带参数SC_DRAGMOVE)

    procedure imgListMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ...

  6. N个数依次入栈,出栈顺序有多少种

    题目:N个数依次入栈,出栈顺序有多少种? 首先介绍一下卡特兰数:卡特兰数前几项为 : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 2 ...

  7. MSSQL 日期操作函数 总结

    set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go ALTER FUNCTION [dbo].[ufn_getDateOfWeek] (@Date Dateti ...

  8. [Leetcode][Python]19: Remove Nth Node From End of List

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 38: Count and Sayhttps://oj.leetcode.co ...

  9. aix rksh 执行CLI命令行限制

    su padmin -C "lsdev -dev hdisk9 -attr| grep unique_id"rksh: lsdev: 0403-006 Execute permis ...

  10. Is life always hard?

    原文来自我的独立blog: http://www.yuanyong.org/blog/midnightsun/is-life-always-hard 和两个朋友聊天. 小L在考研,打电话过去的时候小L ...