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;
}

浙公网安备 33010602011771号