Loading

P14400 [JOISC 2016] 回转寿司 / Sushi

小清新 DS 题。

看到数据范围直接考虑分块,设块长为 \(B\)

对于整块,每次显然换出来的是块内最大值,直接开个大根堆就没了。

对于散块,考虑每次换进去的那个数 \(x\) 组成的集合,\(cur\) 为其中最小值,那么对于当前块内第一个数,如果其 \(> mn\),显然在当时其会把 \(mn\) 换进来,那么会把自己加到集合里,于是开个小根堆维护 tag,每次重构一下就做完了。

时间复杂度 \(\mathcal{O}(q(B + \frac{n}{B}) \log n)\),取 \(B = \sqrt{n}\) 得到复杂度 \(\mathcal{O}(q \sqrt{n} \log n)\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128 i128;
typedef pair<int, int> pii;
const int N = 4e5 + 10, B = 633, mod = 998244353;
template<typename T>
void dbg(const T &t) { cout << t << endl; }
template<typename Type, typename... Types>
void dbg(const Type& arg, const Types&... args) {
    cout << arg << ' ';
    dbg(args...);
}
namespace Loop1st {
int n, Q, L[B], R[B], bel[N], cnt, a[N];
priority_queue<int>q1[B];
priority_queue<int, vector<int>, greater<int>>q2[B];
void rebuild(int id) {
    auto &pq = q2[id];
    if (pq.empty()) return ;
    for (int i = L[id]; i <= R[id]; i++) if (a[i] > pq.top()) {
        pq.push(a[i]);
        a[i] = pq.top();
        pq.pop();
    }
    priority_queue<int, vector<int>, greater<int>>().swap(pq); // <=> pq.clear() 虽然 pq 没有 clear() 函数
}
int query(int l, int r, int x) {
    int bl = bel[l], br = bel[r];
    if (bl == br) {
        rebuild(bl);
        for (int i = l; i <= r; i++) if (a[i] > x) swap(a[i], x);
        priority_queue<int>(a + L[bl], a + R[bl] + 1).swap(q1[bl]); // 即令 q1[bl] = {a[L[bl]], a[L[bl] + 1], ..., a[R[bl]]}
        return x;
    }
    rebuild(bl); rebuild(br);
    for (int i = l; i <= R[bl]; i++) if (a[i] > x) swap(a[i], x);
    priority_queue<int>(a + L[bl], a + R[bl] + 1).swap(q1[bl]);
    for (int i = bl + 1; i < br; i++) {
        if (x >= q1[i].top()) continue;
        q2[i].push(x);
        q1[i].push(x);
        x = q1[i].top();
        q1[i].pop();
    }
    for (int i = L[br]; i <= r; i++) if (a[i] > x) swap(a[i], x);
    priority_queue<int>(a + L[br], a + R[br] + 1).swap(q1[br]);
    return x;
}
void main() {
    cin >> n >> Q;
    cnt = (n + B - 1) / B;
    for (int i = 1; i <= cnt; i++) {
        L[i] = R[i - 1] + 1;
        R[i] = i * B;
    }
    R[cnt] = n;
    for (int i = 1; i <= n; i++) {
        bel[i] = (i + B - 1) / B;
        cin >> a[i];
        q1[bel[i]].push(a[i]);
    }
    while (Q--) {
        int l, r, x; cin >> l >> r >> x;
        if (l > r) cout << query(1, r, query(l, n, x)) << '\n';
        else cout << query(l, r, x) << '\n';
    }
}

}
int main() {
    // freopen("data.in", "r", stdin);
    // freopen("data.out", "w", stdout);
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) Loop1st::main();
    return 0;
}

posted @ 2026-01-08 21:55  循环一号  阅读(3)  评论(0)    收藏  举报