AUPC 2018 day3 B: Pivots

問題

数列a0, ..., an-1が与えられる。要素は互いにことなる。
この数列に対してQ個のクエリを処理した後の数列を出力せよ。
クエリ: 値vが与えられる。ai = vとしたとき、
数列を ai+1, ..., an-1, ai, a0, ..., ai-1のように並び替える。

制約

n, q≦10^5

方針

数列を双方向リストでもつ。クエリは値なので、並び替えをしても値へのポインタをもっておける。
並び替えは繋ぎ変えをすればクエリが一つO(1)で処理できる。


とはいえ実装がかなり面倒だった。平衡二分木ライブラリでやったほうが楽かもしれない。

ソースコード

const int MX = 100020;
int L[MX], R[MX], n, q;

int main() {
	cin >> n >> q;
	using vi = vector<int>;

	vi v(n);
	rep(i, n) cin >> v[i];
	vi vs = v;
	sort(all(vs));
	rep(i, n){
		v[i] = 1 + lower_bound(all(vs), v[i]) - vs.begin();
	}
	rep(i, n + 1){
		int x = i ? v[i - 1] : 0;
		L[x] = i > 1 ? v[i - 2] : 0;
		R[x] = i < n ? v[i] : n + 1;
	}
	L[n + 1] = v[n - 1];
	#if 0
	cerr<<endl;
	rep(i, n+1) cerr<<v[i]<<(i==n?"\n":" ");
	rep(i, n + 1) cerr<<i<<" "<<L[i]<<" "<<R[i]<<endl;
	#endif
	while(q--){
		int x; cin >> x;
		if(n == 1) continue;

		x = 1 + lower_bound(all(vs), x) - vs.begin();
		int a = R[0], A = L[x], b = R[x], B = L[n + 1];
		if(A > 0 && b <= n){
			//cerr<<"! "<<a<<" "<<A<<" "<<x<<" "<<b<<" "<<B<<endl;
			R[0] = b; L[b] = 0;
			R[B] = x; L[x] = B;
			R[x] = a; L[a] = x;
			R[A] = n + 1; L[n + 1] = A;
		}
		else if(b == n + 1){
			R[0] = x; L[x] = 0;
			R[x] = a; L[a] = x;
			R[A] = n + 1; L[n + 1] = A;
		}
		else if(A == 0){
			R[0] = b; L[b] = 0;
			R[B] = x; L[x] = B;
			R[x] = n + 1; L[n + 1] = x;
		}
		else assert(0);
	}
	int r = 0;
	rep(i, n){
		r = R[r];
		cout << vs[r - 1] << (i == n-1?"\n":" ");
	}

	return 0;
}