QOJ3031. Bookstore
非常像数字游戏,再写一遍做法当复习了。
容易转化为赋值为 \(0 / 1\) 序列,如果 \(a_i \in [l, r]\),则设为 \(1\),查询则为 \(\sum \frac{len(len + 1)}{2}\)。
这很莫队。加入是简单的:每个连续的 \(1\) 段左右端点分别存下右左端点。将一个位置改为 \(1\) 的话,就相当于是合并两段 \(1\) 段。但你会发现删除一个位置是困难的。
于是回滚莫队即可。复杂度根号。
这题良心的是全局查,这样避免了再序列分块多维护一车东西。
#include <bits/stdc++.h>
#define _for(i, a, b) for (int i = (a); i <= (b); i ++ )
#define _all(i, a, b) for (int i = (a); i >= (b); i -- )
#define PII pair<int, int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
using namespace std;
namespace IO {
const int LIM = 1e5;
static char buf[LIM], * p1 = buf, * p2 = buf, obuf[LIM], * p3 = obuf, cc[20];
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, LIM, stdin), p1 == p2) ? EOF : * p1 ++ )
#define pc(x) (p3 - obuf < LIM) ? ( * p3 ++ = x) : (fwrite(obuf, p3 - obuf, 1, stdout), p3 = obuf, * p3 ++ = x)
inline int rd() {
int val = 0, sgn = 1; char ch = gc();
for ( ; ch < '0' || ch > '9'; ch = gc()) if (ch == '-') sgn = - 1;
for ( ; ch >= '0' && ch <= '9'; ch = gc()) val = (val << 3) + (val << 1) + (ch ^ 48); return (val * sgn);
} inline void wt(ll x, char c) {
if ( ! x) pc('0'); int len = 0;
if (x < 0) x = - x, pc('-');
while (x) cc[len ++ ] = x % 10 | '0', x /= 10;
while (len -- ) pc(cc[len]); pc(c);
}
} using namespace IO;
const int N = 1e6 + 5;
int n, q, V, B, cnt, qcnt, ed[N], L[N], R[N], a[N], bel[N]; ll res, ans[N]; PII val[N], updL[N], updR[N];
struct Node { int l, r, id; } qry[N];
inline void upd_l(int x, int k) { updL[ ++ cnt] = mp(x, L[x]), L[x] = k; }
inline void upd_r(int x, int k) { updR[cnt] = mp(x, R[x]), R[x] = k; }
inline ll calc(int x) { return 1ll * x * (x + 1) / 2; }
inline void add(int op, int x) {
if ( ! op) {
if (L[x - 1] && R[x + 1]) R[L[x - 1]] = R[x + 1], L[R[x + 1]] = L[x - 1], res += calc(R[x + 1] - L[x - 1] + 1) - calc(x - L[x - 1]) - calc(R[x + 1] - x);
else if (L[x - 1]) R[L[x - 1]] = x, L[x] = L[x - 1], res += x - L[x - 1] + 1;
else if (R[x + 1]) L[R[x + 1]] = x, R[x] = R[x + 1], res += R[x + 1] - x + 1;
else L[x] = R[x] = x, res ++ ;
} else {
if (L[x - 1] && R[x + 1]) upd_l(R[x + 1], L[x - 1]), upd_r(L[x - 1], R[x + 1]), res += calc(R[x + 1] - L[x - 1] + 1) - calc(x - L[x - 1]) - calc(R[x + 1] - x);
else if (L[x - 1]) upd_l(x, L[x - 1]), upd_r(L[x - 1], x), res += x - L[x - 1] + 1;
else if (R[x + 1]) upd_l(R[x + 1], x), upd_r(x, R[x + 1]), res += R[x + 1] - x + 1;
else upd_l(x, x), upd_r(x, x), res ++ ;
}
} inline ll calc(int op, int l, int r) {
ll tmp = res, t;
_for (i, l, op ? ed[bel[l]] : r) add(1, val[i].se);
_all (i, cnt, 1) L[updL[i].fi] = updL[i].se, R[updR[i].fi] = updR[i].se; cnt = 0, t = res, res = tmp; return t;
} inline void solve() {
n = rd(), q = rd(), B = sqrt(n); int l, r, cur, j; res = qcnt = 0;
_for (i, 1, n) bel[i] = (i - 1) / B + 1;
_for (i, 1, n) a[i] = rd(), val[i] = mp(a[i], i); sort(val + 1, val + n + 1, [&] (PII u, PII v) { return u.fi < v.fi; });
_for (i, 1, bel[n]) ed[i] = min(n, i * B);
_for (i, 1, q) {
l = rd(), r = rd(); int LL = 1, RR = n, mid, pos = n + 1;
while (LL <= RR) {
mid = (LL + RR) >> 1;
if (val[mid].fi >= l) pos = mid, RR = mid - 1;
else LL = mid + 1;
} l = pos, pos = 0, LL = 1, RR = n;
while (LL <= RR) {
mid = (LL + RR) >> 1;
if (val[mid].fi <= r) pos = mid, LL = mid + 1;
else RR = mid - 1;
} r = pos;
if (l > r) ans[i] = 0;
else if (bel[l] == bel[r]) ans[i] = calc(0, l, r);
else qry[ ++ qcnt] = (Node){l, r, i};
} sort(qry + 1, qry + qcnt + 1, [&] (Node u, Node v) { return bel[u.l] ^ bel[v.l] ? bel[u.l] < bel[v.l] : u.r < v.r; }), j = 1;
_for (i, 1, bel[n]) {
cur = ed[i];
while (j <= qcnt && bel[qry[j].l] < i) j ++ ;
while (j <= qcnt && bel[qry[j].l] == i) { { while (cur < qry[j].r) add(0, val[ ++ cur].se); } ans[qry[j].id] = calc(1, qry[j].l, qry[j].r), j ++ ; }
_for (j, 1, n) L[j] = R[j] = 0; res = 0;
} _for (i, 1, q) wt(ans[i], '\n');
}
int main() {
ios :: sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T = rd(); while (T -- ) solve();
return fwrite(obuf, p3 - obuf, 1, stdout), 0;
}

浙公网安备 33010602011771号