CF356A Knight Tournament
阿新 • • 發佈:2021-11-17
題目大意
有 \(n\) 個騎士,他們每個人都被從 \(1-n\) 進行編號。
他們現在需要進行一次比賽,且總共會進行 \(m\) 場比賽。
每場比賽會在編號在 \(L_i-R_i\) 這段區間內的騎士之間舉行,對於每場比賽,它的勝利者的編號為 \(X_i\),其他的騎士會出局,之後無法進行比賽。最後留下的騎士就是這次比賽的最終勝利者。
比賽結束後,每個騎士都想知道他被哪一個騎士擊敗了,請你告訴他們。
解題思路
首先可以想到,\(L_i - R_i\) 所有人被 \(X_i\) 擊敗。
那麼可以用線段樹將這一段標記為 \(X_i\)。
但是會有一個問題,如果一個數 \(op\),被多個區間包含,那麼只能算被第一個區間擊敗。
所以將事件倒序處理即可。
時間複雜度 \(\mathcal O(m \log n)\)。
CODE
#include <bits/stdc++.h> using namespace std; const int _ = 5e5 + 7; int n, m; int l[_], r[_], x[_]; int tr[_ << 2]; void push_down(int o) { if(tr[o]) { tr[o << 1] = tr[o]; tr[o << 1 | 1] = tr[o]; tr[o] = 0; } } void update(int o, int l, int r, int L, int R, int val) { if(r < L || l > R) return; if(L <= l && r <= R) { tr[o] = val; return; } push_down(o); int mid = (l + r) >> 1; update(o << 1, l, mid, L, R, val); update(o << 1 | 1, mid + 1, r, L, R, val); } void print(int o, int l, int r) { if(l == r) { cout << tr[o] << " "; return; } push_down(o); int mid = (l + r) >> 1; print(o << 1, l, mid); print(o << 1 | 1, mid + 1, r); } signed main() { cin >> n >> m; for(int i = 1; i <= m; ++i) cin >> l[i] >> r[i] >> x[i]; for(int i = m; i >= 1; --i) { if(x[i] == l[i]) { update(1, 1, n, l[i] + 1, r[i], x[i]); } else if(x[i] == r[i]) { update(1, 1, n, l[i], r[i] - 1, x[i]); } else { update(1, 1, n, l[i], x[i] - 1, x[i]); update(1, 1, n, x[i] + 1, r[i], x[i]); } } print(1, 1, n); return 0; }
本文來自部落格園,作者:蒟蒻orz,轉載請註明原文連結:https://www.cnblogs.com/orzz/p/15553529.html