POJ 2274

关于逆序数和堆的问题,这里很巧妙地从全局切入,即,每一次即将发生的超车,必定是超过他前面相邻的车(虽然具体到每一辆车,他不一定超过的就是他面前的车,但是要从全局考虑)。

  • 之后维护堆有一点注意,因为堆不可以按照索引任意修改堆中元素,我们干脆就在堆中保留那些陈旧的节点,取出来的时候出现问题直接丢掉,而是去选择节点中记录的前一辆车信息,与我们实时更新的总表中前一辆车信息一致的节点。
  • 每次更新的时候,就是唯一可能出现新的堆中节点的时候。
  • 更新每辆车前面最近邻和后面最近邻的时候,类似于链表更新连接时的操作
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;

const int maxn= 25e4+5;
const int INF= 0x3f3f3f3f;

int a[maxn], b[maxn], x[maxn], v[maxn], vb[maxn], vt[maxn];
int inv;
struct T
{
	int tu, td;
	T(){}
	T(int ttu, int ttd) : tu(ttu), td(ttd) {}
	bool operator > (const T &z) const 
	{
		return tu*z.td > td*z.tu;
	}
	bool operator == (const T &z) const
	{
		return tu*z.td == td*z.tu;
	}
};
struct Record
{
	int i;
	int ai;
	T t;
	double mp;
	Record(){}
	Record(int ii, int aai, T tt) : i(ii), ai(aai), t(tt) 
	{
		mp= x[i]+v[i]*1.0*t.tu/t.td;
	}
	bool operator < (const Record &z) const
	{
		if (t> z.t){
			return true;
		}
		if (t== z.t && mp > z.mp){
			return true;
		}
		return false;
	}
};
priority_queue<Record> hp;


void Merge(int l, int r)
{
	int m= (l+r)>>1;
	int i= l, j= m+1;
	int k= l;

	while (i<= m && j<= r){
		if (vb[i]> vb[j]){
			vt[k++]= vb[j++];
			inv+= m-i+1;
			inv%= 1000000;
		}
		else{
			vt[k++]= vb[i++];
		}
	}
	while (i<= m){
		vt[k++]= vb[i++];
	}
	while (j<= r){
		vt[k++]= vb[j++];
	}

	for (i= l; i<= r; ++i){
		vb[i]= vt[i];
	}
}
void MergeSort(int l, int r)
{
	if (l>= r){
		return;
	}

	int m= (l+r)>>1;
	MergeSort(l, m);
	MergeSort(m+1, r);
	Merge(l, r);
}
void Init(int n)
{
	inv= 0;
	memset(x, -1, sizeof(x));
	memset(v, -1, sizeof(v));
	v[n+1]= INF;
	x[n+1]= 1e8;
}

int main()
{
	int n, m, dv, dx;
	T t;
	scanf("%d", &n);

	Init(n);
	for (int i= 1; i<= n; ++i){
		scanf("%d %d", x+i, v+i);
		vb[i]= v[i];
		a[i]= i+1;
		b[i]= i-1;
	}

	for (int i= 1; i<= n; ++i){
		dx= x[a[i]]-x[i];
		dv= v[i]-v[a[i]];
		if (dv > 0){
			t= T(dx, dv);
			hp.push(Record(i, a[i], t));
		}
	}

	MergeSort(1, n);
	cout<<inv<<endl;

	m= inv > 10000 ? 10000 : inv;
	while (m--){
		Record tp= hp.top();
		hp.pop();

		while (tp.ai!= a[tp.i]){
			tp= hp.top();
			hp.pop();
		}

		a[b[tp.i]]= tp.ai;
		b[a[tp.ai]]= tp.i;
		a[tp.i]= a[tp.ai];
		b[tp.ai]= b[tp.i];
		a[tp.ai]= tp.i;
		b[tp.i]= tp.ai;

		dv= v[tp.i]- v[a[tp.i]];
		if (dv > 0){
			dx= x[a[tp.i]]- x[tp.i];
			t= T(dx, dv);
			hp.push(Record(tp.i, a[tp.i], t));
		}

		dv= v[b[tp.ai]]- v[tp.ai];
		if (dv > 0){
			dx= x[tp.ai]- x[b[tp.ai]];
			t= T(dx, dv);
			hp.push(Record(b[tp.ai], tp.ai, t));
		} 

		printf("%d %d
", tp.i, tp.ai);
	}

	return 0;
}
原文地址:https://www.cnblogs.com/Idi0t-N3/p/13330666.html