【单调栈+倍增】[P7167 [eJOI2020 Day1] Fountain

【单调栈+倍增】[P7167 [eJOI2020 Day1] Fountain

思路

用单调栈处理每个圆盘溢出后流到的第一个位置,然后倍增优化。

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;

    vector<array<i64, 2>> a(n + 1);
    for (int i = 1; i <= n; i ++) {
        cin >> a[i][0] >> a[i][1];
    }

    n ++;
    a.push_back({INT_MAX, INT_MAX});
    vector jump(n + 1, vector<int>(20));
    vector sum(n + 1, vector<i64>(20, INT_MAX));

    stack<int> st;
    for (int i = 1; i <= n; i ++) {
        while (st.size() && a[i][0] > a[st.top()][0]) {
            auto t = st.top();
            jump[t][0] = i;
            sum[t][0] = a[t][1];
            st.pop();
        }
        st.push(i);
    }

    for (int j = 1; (1 << j) <= n; j ++) {
        for (int i = 1; i + (1 << j) <= n; i ++) {
            jump[i][j] = jump[jump[i][j - 1]][j - 1];
            sum[i][j] = sum[jump[i][j - 1]][j - 1] + sum[i][j - 1];
        }
    }

    auto query = [&](int r, int v)->int{
        for (int i = 18; i >= 0; i --) {
            if (v > sum[r][i]) {
                v -= sum[r][i];
                r = jump[r][i];
            }
        }
        return r % n;
    };

    while (m --) {
        int r, v;
        cin >> r >> v;
        cout << query(r, v) << '\n';
    }

    return 0;
}
posted @ 2024-08-12 19:56  Ke_scholar  阅读(7)  评论(0编辑  收藏  举报