This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
const long long M = 1e9 + 7;
const int INF = 2147483647;
const long long INFLL = 9223372036854775807ll;
#pragma region Template Start
#include <algorithm>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
// template <typename T>
// using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
// template <typename T>
// using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
using tiii = tuple<int, int, int>;
using tlll = tuple<ll, ll, ll>;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vpii = vector<pii>;
using vpll = vector<pll>;
#define endl '\n'
#define nl cout << '\n'
#define pb push_back
#define pob pop_back
#define mp make_pair
#define mt make_tuple
#define ff first
#define ss second
#define FIX(number, digits) fixed << setprecision(digits) << number // use in cout
#define fok(i, k, n) for (ll i = k; i < n; i++)
#define Fok(i, k, n) for (ll i = n; i >= k; i--)
#define fo(i, n) for (ll i = 0; i < n; i++)
#define Fo(i, n) for (ll i = n; i >= 0; i--)
#define CHK(s, k) (s.find(k) != s.end())
#define all(v) v.begin(), v.end()
#define allg(v) v.rbegin(), v.rend()
#define Sort(v) sort(all(v))
#define Sortg(v) sort(allg(v))
#define sz(v) (static_cast<ll>(v.size()))
#define bs(v, val) binary_search(all(v), val)
#define lb(v, val) lower_bound(all(v), val)
#define ub(v, val) upper_bound(all(v), val)
#define setbits(x) __builtin_popcount(x)
#define start_clock() auto start_time = std::chrono::high_resolution_clock::now()
#define measure() \
auto end_time = std::chrono::high_resolution_clock::now(); \
cerr << (end_time - start_time) / std::chrono::milliseconds(1) << "ms" << endl
#define fastio \
ios_base::sync_with_stdio(false); \
cin.tie(NULL); \
cout.tie(NULL)
#define fileio \
freopen("input.txt", "r", stdin); \
freopen("output.txt", "w", stdout)
#pragma endregion Template End
class RangeCountHelper {
public:
RangeCountHelper(int n) {
this->n = n;
this->st.resize(4 * n, 0);
}
int getCount(int l, int r) {
return this->_query(l, r, 0, n - 1, 0);
}
void switchOn(int index) {
this->_update(index, 0, n - 1, 0);
}
private:
vector<int> st;
int n;
int _query(int l, int r, int sl, int sr, int idx) {
if (l > sr || r < sl || sl > sr)
return 0;
if (sl >= l && sr <= r)
return st[idx];
int mid = (sl + sr) / 2;
return _query(l, r, sl, mid, idx * 2 + 1) + _query(l, r, mid + 1, sr, idx * 2 + 2);
}
void _update(int i, int sl, int sr, int idx) {
if (i > sr || i < sl)
return;
if (sl == sr) {
st[idx] = 1;
return;
}
int mid = (sl + sr) / 2;
if (i <= mid)
_update(i, sl, mid, idx * 2 + 1);
else
_update(i, mid + 1, sr, idx * 2 + 2);
st[idx] = st[idx * 2 + 1] + st[idx * 2 + 2];
}
};
class LargestIndexHelper {
public:
LargestIndexHelper(vector<int> &a) {
this->n = a.size();
this->a = a;
this->st.resize(4 * n, 0);
this->_build(0, n - 1, 0);
}
int getLargestIndex(int greaterThanEqualTo) {
return _query(greaterThanEqualTo, 0, n - 1, 0);
}
void invalidate(int index) {
this->_remove(index, 0, n - 1, 0);
}
private:
vector<int> st;
vector<int> a;
int n;
int _query(int k, int sl, int sr, int idx) {
if (st[idx] == -1)
return -1;
if (sl == sr) {
return a[sl] >= k ? sl : -1;
}
if (st[idx] != -1 && a[st[idx]] >= k)
return st[idx];
int mid = (sl + sr) / 2;
if (st[idx * 2 + 2] != -1) { // this being -1 means that the whole subarray has been invalidated, so no point
int right = _query(k, mid + 1, sr, idx * 2 + 2);
if (right != -1)
return right;
} //arpitpandey992 => Not the best IITR-EE has to offer
else if (st[idx * 2 + 1] != -1)
return _query(k, sl, mid, idx * 2 + 1);
return -1;
}
void _remove(int i, int sl, int sr, int idx) {
if (i > sr || i < sl)
return;
if (sl == sr) {
a[i] = -1; // this will no longer be considered during query
st[idx] = -1; // for optimization?
return;
}
int mid = (sl + sr) / 2;
if (i <= mid)
_remove(i, sl, mid, idx * 2 + 1);
else
_remove(i, mid + 1, sr, idx * 2 + 2);
st[idx] = max(st[idx * 2 + 1], st[idx * 2 + 2]);
}
int _build(int sl, int sr, int idx) {
if (sl == sr) {
return st[idx] = sl;
}
int mid = (sl + sr) / 2;
int left = _build(sl, mid, idx * 2 + 1);
int right = _build(mid + 1, sr, idx * 2 + 2);
return st[idx] = max(left, right);
}
};
void solve() {
int n, k;
cin >> n >> k;
vector<pair<int, int>> a(n);
vector<int> queries(k);
fo(i, n) {
cin >> a[i].first >> a[i].second;
}
sort(a.begin(), a.end(), [](auto &p1, auto &p2) { return max(p1.ff, p1.ss) > max(p2.ff, p2.ss); });
fo(i, k) {
cin >> queries[i];
}
RangeCountHelper rangeCountHelper(queries.size());
LargestIndexHelper largestIndexHelper(queries);
vector<pair<int, int>> q;
for (int i = 0; i < k; i++) {
q.push_back({queries[i], i});
}
sort(q.begin(), q.end());
ll ans = 0;
for (auto &[ai, bi] : a) {
while (q.size() && q.back().ff >= max(ai, bi)) {
auto [currentMaxQuery, currentMaxQueryIndex] = q.back();
q.pop_back();
rangeCountHelper.switchOn(currentMaxQueryIndex);
largestIndexHelper.invalidate(currentMaxQueryIndex);
}
int largestIndex = largestIndexHelper.getLargestIndex(min(ai, bi));
int rotationCount = rangeCountHelper.getCount(largestIndex + 1, k - 1);
bool isRotated = rotationCount % 2 == 1;
if (ai < bi) {
if (largestIndex != -1)
isRotated = !isRotated;
}
ans += isRotated ? (ll)bi : (ll)ai;
}
cout << ans << endl;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
ll tes = 1;
// cin >> tes;
for (ll t = 1; t <= tes; t++) {
// cout << "Case #" << t << ": ";
solve();
}
}
/*
What to do?
1. for any query q[i] >= a[i].ss && q[i] < a[i].ff (assuming first > second)
- This will cause rotation to revert back to initial state (above assumption)
- After last q[i] >= ... && q[i] < ..., all q[i] >= a[i].ff will rotate once
2. find the last query index whose value is lesser than a[i].ff but >= a[i].ss
- max index in array whose value is >= given value [queries]
- since we are iterating in reducing value of a[i].ff, we can permanently ignore them when calculating maxIndex
- basically largest index with value >= given query
3. rotationCount = number of q[i] where i > above index && q[i] >= a[i].ff
- willRotate = rotationCount%2 == 1
- if a[i].ff < a[i].ss:
- rotation will still count in the same way, just that we assume we start from bigger value as first
- if no query between a[i].ff and a[i].ss, then rotation will count from smaller value (edge case).
4. when iterating in reverse manner of a[i].ff, the above count will only increase
- simple range sum query in binary array
- initially, all zero
- while iterating on a, make imaginaryArray[j] = 1 where q[j] >= a[i].ff
*/
Compilation message (stderr)
fortune_telling2.cpp:4: warning: ignoring '#pragma region Template' [-Wunknown-pragmas]
4 | #pragma region Template Start
|
fortune_telling2.cpp:87: warning: ignoring '#pragma endregion Template' [-Wunknown-pragmas]
87 | #pragma endregion Template End
|
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |