#include //#include using namespace std; // using namespace atcoder; // using mint = modint1000000007; // const int mod = 1000000007; // using mint = modint998244353; // const int mod = 998244353; // const int INF = 1e9; const long long LINF = 1e18; #define rep(i, n) for (int i = 0; i < (n); ++i) #define rep2(i, l, r) for (int i = (l); i < (r); ++i) #define rrep(i, n) for (int i = (n)-1; i >= 0; --i) #define rrep2(i, l, r) for (int i = (r)-1; i >= (l); --i) #define all(x) (x).begin(), (x).end() #define allR(x) (x).rbegin(), (x).rend() #define P pair template inline bool chmax(A& a, const B& b) { if (a < b) { a = b; return true; } return false; } template inline bool chmin(A& a, const B& b) { if (a > b) { a = b; return true; } return false; } #ifndef KWM_T_ALGORITHM_SEARCH_DOUBLING_HPP #define KWM_T_ALGORITHM_SEARCH_DOUBLING_HPP #include #include #include namespace kwm_t::algorithm::search { /** * @brief Doubling (Binary Lifting) * * 関数 f の k 回適用 f^k(x) を高速に求めるデータ構造。 * nxt[v] = f(v) としたとき、 * 2^i 回遷移した先を前計算することで O(log k) で遷移可能。 * * value を持たせることで、遷移に伴う値(距離・重み・xor など)の * 累積も同時に計算できる。 * * 典型用途: * ・Functional Graph の k step * ・テレポート問題 * ・祖先ジャンプ * ・遷移コストの累積 * * 計算量: * 構築 O(N log K) * jump / jump_value / first_true : O(log K) * * @tparam T 遷移に付随する値の型 * @tparam Merge 値をマージする関数 (例: std::plus) * * @param nxt nxt[v] = v から1回遷移した先 * @param value 各遷移に対応する値 * @param log 最大ステップ数のビット長 * * 制約 / 注意: * ・first_true は単調性が必要 * f(jump(v,k)) が * false false ... false true true ... * の形になる必要がある * * 使用例: * vector nxt = {...}; * Doubling<> db(nxt); * int v = db.jump(0, 1e18); * * vector cost = {...}; * auto merge = [](auto a, auto b) { return a + b; }; * Doubling db2(nxt, cost, merge); * auto [to, sum] = db2.jump_value(0, k); * * verified: * https://atcoder.jp/contests/awc0025/submissions/74048140 * https://atcoder.jp/contests/abc438/submissions/74048565 * first_true * https://atcoder.jp/contests/arc218/submissions/75493507 */ struct DoublingNoValue {}; template> class Doubling { public: int N; int LOG; Doubling(const std::vector& nxt, int log = 60) : N((int)nxt.size()), LOG(log) { init(nxt); } Doubling(const std::vector& nxt, const std::vector& value, Merge m = Merge(), int log = 60) : N((int)nxt.size()), LOG(log), merge(m) { init(nxt, value); } // k回遷移 int jump(int v, long long k) const { for (int i = 0; i < LOG; ++i) { if (k >> i & 1) v = to[i][v]; } return v; } // value付き k回遷移 std::pair jump_value(int v, long long k) const { T res{}; for (int i = 0; i < LOG; ++i) { if (k >> i & 1) { res = merge(res, val[i][v]); v = to[i][v]; } } return { v, res }; } // f(jump(v,k)) が true になる最小 k (存在しなければ -1) template long long first_true(int v, long long limit, F f) const { T acc{}; if (f(v, acc)) return 0; long long k = 0; for (int i = LOG - 1; i >= 0; --i) { if (k + (1LL << i) > limit) continue; int nv = to[i][v]; T nacc; if constexpr (std::is_same_v) nacc = acc; else nacc = merge(acc, val[i][v]); if (!f(nv, nacc)) { v = nv; acc = nacc; k += 1LL << i; } } if (k == limit) return -1; return k + 1; } private: std::vector> to; std::vector> val; Merge merge; void init(const std::vector& nxt) { to.assign(LOG, std::vector(N)); to[0] = nxt; for (int i = 1; i < LOG; ++i) { for (int v = 0; v < N; ++v) { to[i][v] = to[i - 1][to[i - 1][v]]; } } } void init(const std::vector& nxt, const std::vector& value) { to.assign(LOG, std::vector(N)); val.assign(LOG, std::vector(N)); to[0] = nxt; val[0] = value; for (int i = 1; i < LOG; ++i) { for (int v = 0; v < N; ++v) { int u = to[i - 1][v]; to[i][v] = to[i - 1][u]; val[i][v] = merge(val[i - 1][v], val[i - 1][u]); } } } }; } // namespace kwm_t::algorithm::search #endif // KWM_T_ALGORITHM_SEARCH_DOUBLING_HPP int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, m, q; cin >> n >> m >> q; vectorl(m), r(m); rep(i, m) { cin >> l[i] >> r[i]; l[i]--, r[i]--; } vectort(q), x(q); vector sh(m, vector>()); // t kai ato no a[x] rep(i, q) { cin >> t[i] >> x[i]; x[i]--; sh[t[i] % m].emplace_back(x[i], i); t[i] /= m; } vectora(n); rep(i, n)a[i] = i; rep(i, m) { for (auto [xx, idx] : sh[i]) { x[idx] = a[xx]; } swap(a[l[i]], a[r[i]]); } kwm_t::algorithm::search::Doubling db(a); rep(i, q) { auto ans = db.jump(x[i], t[i]); cout << ans + 1 << endl; } return 0; }