Hướng dẫn giải của Eo Xi Cây Cúp
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 7; const int INF = 1e9 + 7; int smaller_team[MAXN], greater_team[MAXN]; bool is_smaller_team[MAXN]; set<int> smaller_teams; struct Node { int last_team_group[2]; int bounded[2]; int last_greater_team; int first_smaller_team; Node(int _smaller_team = -1, int _greater_team = -1) { first_smaller_team = _smaller_team == -1 ? INF : _smaller_team; last_greater_team = _greater_team == -1 ? -INF : _greater_team; last_team_group[0] = last_team_group[1] = 1; bounded[0] = bounded[1] = 1; if (_smaller_team != -1) { if (_greater_team != _smaller_team) { last_team_group[1] = 0; bounded[0] = 0; } else { last_team_group[0] = 0; bounded[1] = 1; } } } Node operator + (const Node& other) const { Node res; if (first_smaller_team == INF) { return other; } if (other.first_smaller_team == INF) { return *this; } res.first_smaller_team = first_smaller_team; res.last_greater_team = other.last_greater_team; bool change0 = (last_greater_team > other.first_smaller_team) && (bounded[0] == 0); bool change1 = (last_greater_team > other.first_smaller_team) && (bounded[1] == 0); res.last_team_group[0] = change0 ? (last_team_group[0] ^ other.last_team_group[1]) : (1 ^ last_team_group[0] ^ other.last_team_group[0]); res.last_team_group[1] = change1 ? (last_team_group[1] ^ other.last_team_group[1]) : (1 ^ last_team_group[1] ^ other.last_team_group[0]); res.bounded[0] = change0 ? other.bounded[1] : other.bounded[0]; res.bounded[1] = change1 ? other.bounded[1] : other.bounded[0]; return res; } }; struct SegmentTree { vector<Node> tree; int n; SegmentTree(int _n = 0) { n = _n; tree.resize(n * 4 + 7); } void init(int id, int l, int r) { if (l == r) { if (is_smaller_team[l]) { tree[id] = Node(l, greater_team[l]); } else { tree[id] = Node(-1, -1); } return; } int mid = (l + r) / 2; init(id * 2, l, mid); init(id * 2 + 1, mid + 1, r); tree[id] = tree[id * 2] + tree[id * 2 + 1]; } void init() { init(1, 1, n); } void update(int id, int l, int r, int pos) { if (l == r) { if (is_smaller_team[l]) { tree[id] = Node(l, greater_team[l]); } else { tree[id] = Node(-1, -1); } return; } int mid = (l + r) / 2; if (pos <= mid) { update(id * 2, l, mid, pos); } else { update(id * 2 + 1, mid + 1, r, pos); } tree[id] = tree[id * 2] + tree[id * 2 + 1]; } void update(int pos) { update(1, 1, n, pos); } Node get(int id, int l, int r, int u, int v) { if (l > v || r < u) { return Node(-1, -1); } if (l >= u && r <= v) { return tree[id]; } int mid = (l + r) / 2; return get(id * 2, l, mid, u, v) + get(id * 2 + 1, mid + 1, r, u, v); } Node get(int u, int v) { return get(1, 1, n, u, v); } }; int n, m, q; void solve() { cin >> n >> m; while (!smaller_teams.empty()) { smaller_teams.erase(smaller_teams.begin()); } for (int i = 1; i <= n * 2; ++i) { is_smaller_team[i] = true; greater_team[i] = i; smaller_team[i] = i; smaller_teams.insert(i); } for (int i = 1; i <= m; ++i) { int x, y; cin >> x >> y; if (x > y) { swap(x, y); } is_smaller_team[x] = true; is_smaller_team[y] = false; smaller_team[x] = smaller_team[y] = x; greater_team[x] = greater_team[y] = y; smaller_teams.erase(y); } SegmentTree it = SegmentTree(n * 2); it.init(); cin >> q; for (int i = 1; i <= q; ++i) { char type; cin >> type; if (type == '+') { int x, y; cin >> x >> y; if (x > y) { swap(x, y); } is_smaller_team[x] = true; is_smaller_team[y] = false; smaller_team[x] = smaller_team[y] = x; greater_team[x] = greater_team[y] = y; smaller_teams.erase(y); it.update(x); it.update(y); } else if (type == '-') { int x, y; cin >> x >> y; if (x > y) { swap(x, y); } is_smaller_team[x] = true; is_smaller_team[y] = true; smaller_team[x] = greater_team[x] = x; smaller_team[y] = greater_team[y] = y; smaller_teams.insert(y); it.update(x); it.update(y); } else { int x; cin >> x; Node tmp = it.get(1, smaller_team[x] - 1); bool change = (tmp.last_greater_team > smaller_team[x]) && (tmp.bounded[0] == 0); if (change) { cout << tmp.last_team_group[0] << '\n'; } else { auto itr = smaller_teams.upper_bound(smaller_team[x]); if (is_smaller_team[x] || (itr != smaller_teams.end() && *itr < x)) { cout << (1 ^ tmp.last_team_group[0]) << '\n'; } else { cout << tmp.last_team_group[0] << '\n'; } } } } } int main() { #ifdef LOCAL freopen("main.inp", "r", stdin); freopen("main.out", "w", stdout); #endif ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t; cin >> t; while (t--) { solve(); } return 0; }
Bình luận