Submission #390693

#TimeUsernameProblemLanguageResultExecution timeMemory
390693JimmyZJXArranging Shoes (IOI19_shoes)C++14
100 / 100
287 ms157480 KiB
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cassert>
#include <tuple>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <unordered_set>
#include <unordered_map>

using namespace std;

typedef long long LL;
typedef vector<int> Vi;
typedef vector<bool> Vb;
typedef vector<vector<int>> Vii;

#define forR(i, n) for (int i = 0; i < (n); i++)


struct SegNode {
	SegNode* left = nullptr, * right = nullptr;
	int c = 1;
	int l, r;

	SegNode(int l, int r) {
		this->l = l; this->r = r;
		if (l != r) {
			int mid = (l + r) / 2;
			this->left = new SegNode(l, mid);
			this->right = new SegNode(mid + 1, r);
			c = left->c + right->c;
		}
	}

	int CountRange(int f, int t) {
		if (r < f || l > t) return 0;
		if (f <= l && r <= t) return c;

		return left->CountRange(f, t) + right->CountRange(f, t);
	}

	void Remove(int x) {
		if (r < x || l > x) return;
		if (l == x && r == x) {
			c = 0;
			return;
		}

		left->Remove(x); right->Remove(x);
		c = left->c + right->c;
	}
};



vector<queue<int>> poss;
vector<queue<int>> negs;

inline auto& getQueue(int x) {
	if (x > 0) return poss[x];
	return negs[-x];
}

LL count_swaps(Vi S) {
	int n = S.size() / 2;

	poss = vector<queue<int>>(n + 3);
	negs = vector<queue<int>>(n + 3);

	forR(i, 2 * n) {
		int c = S[i];
		getQueue(c).push(i);
	}

	LL ans = 0;
	if (n <= 1) {
		// task 1, 2, 5
		forR(i, n) {
			int p = i * 2;
			int Sp = S[p];

			int q = p + 1;
			while (S[q] != -Sp) q++;
			while (q > p + 1) {
				swap(S[q], S[q - 1]);
				q--;
				ans++;
			}
			if (S[p] > 0) ans++;
		}
	} else {
		Vb used(2 * n);
		SegNode* root = new SegNode(0, 2 * n - 1);
		forR(i, 2 * n) {
			if (used[i]) continue;

			int x = S[i];
			int q = getQueue(-x).front();

			getQueue(x).pop(); getQueue(-x).pop();

			int count = root->CountRange(i, q);
			ans += count - 2;
			if (x > 0) ans++;
			root->Remove(q);
			used[q] = true;
		}
	}

	return ans;
}

#ifdef TEST_LOCAL
int main() {
	auto c = count_swaps(Vi{ 2, 1, -1, -2 });
	c = count_swaps(Vi{ -2, 2, 2, -2, -2, 2 });

	return 0;
}
#endif

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...