제출 #231873

#제출 시각아이디문제언어결과실행 시간메모리
231873iefnah06운세 보기 2 (JOI14_fortune_telling2)C++11
100 / 100
740 ms28552 KiB
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using ll = long long;

template <typename K, typename V, typename Comp = std::less<K>>
using order_statistic_map = __gnu_pbds::tree<
	K, V, Comp,
	__gnu_pbds::rb_tree_tag,
	__gnu_pbds::tree_order_statistics_node_update
>;

template <typename K, typename Comp = std::less<K>>
using order_statistic_set = order_statistic_map<K, __gnu_pbds::null_type, Comp>;

const int MAXN = 2.1e5;
const int MAXQ = 2.1e5;
int n, q;
int ca[MAXN];
int cb[MAXN];
int qt[MAXQ];

const int S = 1 << 19;
int seg[2 * S];

void update(int i, int v) {
	if (seg[S+i] >= v) return;
	seg[S+i] = v;
	for (int a = (S+i)/2; a; a /= 2) {
		seg[a] = max(seg[2*a], seg[2*a+1]);
	}
}

int query(int l) {
	int res = -1;
	for (int a = S+l, b = S+S; a < b; a /= 2, b /= 2) {
		if (a & 1) {
			res = max(res, seg[a++]);
		}
		if (b & 1) {
			res = max(res, seg[--b]);
		}
	}
	return res;
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);

	cin >> n >> q;
	vector<int> vals;
	for (int i = 0; i < n; i++) {
		cin >> ca[i] >> cb[i];
		vals.push_back(min(ca[i], cb[i]));
	}
	for (int i = 0; i < q; i++) {
		cin >> qt[i];
		vals.push_back(qt[i]);
	}

	sort(vals.begin(), vals.end());
	vals.erase(unique(vals.begin(), vals.end()), vals.end());
	auto lookup = [&](int v) {
		auto it = lower_bound(vals.begin(), vals.end(), v);
		assert(it != vals.end() && *it == v);
		return int(it - vals.begin());
	};

	vector<int> cards(n);
	iota(cards.begin(), cards.end(), 0);
	sort(cards.begin(), cards.end(), [&](int i, int j) {
		return max(ca[i], cb[i]) < max(ca[j], cb[j]);
	});
	vector<int> operations(q);
	iota(operations.begin(), operations.end(), 0);
	sort(operations.begin(), operations.end(), [&](int i, int j) {
		return qt[i] < qt[j];
	});

	order_statistic_set<pair<int, int>> os;
	for (int i = 0; i < q; i++) {
		os.insert({i, qt[i]});
	}
	auto operations_it = operations.begin();
	ll ans = 0;
	for (int a = 1; a < S*2; a++) {
		seg[a] = -1;
	}
	for (auto card : cards) {
		int lo = min(ca[card], cb[card]);
		int hi = max(ca[card], cb[card]);
		while (operations_it != operations.end() && qt[*operations_it] < hi) {
			os.erase({*operations_it, qt[*operations_it]});
			update(lookup(qt[*operations_it]), *operations_it);
			operations_it++;
		}

		int last_time = query(lookup(lo));
		int parity = (os.size() - os.order_of_key({last_time, -1})) % 2;
		if (last_time == -1) {
			ans += parity ? cb[card] : ca[card];
		} else {
			ans += parity ? lo : hi;
		}
	}
	cout << ans << '\n';

	return 0;
}

// Let's assume that a_i < b_i
// t_j < a_i: nothing happens
// a_i <= t_j < b_i: becomes b_i
// b_i <= t_j: flips
// For each card, let's fix the last operation of the second type, then the result only depends on the parity of (# of flips) after that operation
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...