CF803G Periodic RMQ Problem 题解
分析
容易发现,此题可以类似 \(\texttt{ODT}\),将序列分作数块。但为了方便查询一段块的最小值,只能手写平衡树。
平衡树每个结点对应一段,分两种:
- \(b[l,r]\)
此时直接记录 \(l,r\) 以及 \(b[l,r]\) 的最小值即可。 - \(c\) 个 \(v\)
记录 \(c,v\)。
进行操作时,应将左右端点所在块视情况分裂,细节略。
代码
#include<bits/stdc++.h>
namespace IO {
constexpr int bufsize = 230005;
char buf[bufsize], *f1, *f2;
char gtchar() {return f1 == f2 && (f2 = buf + fread(f1 = buf, 1, bufsize, stdin)) == buf? EOF: *f1++;}
template<typename T> void read(T &ret)
{
int f = ret = 0;
char ch = gtchar();
while(!isdigit(ch)) f = ch == '-', ch = gtchar();
while(isdigit(ch)) ret = (ret << 3) + (ret << 1) + (ch ^ 48), ch = gtchar();
if(f) ret = -ret;
}
template<typename T, typename ...t> void read(T &a, t &...b) {read(a), read(b...);}
}using IO::read;
typedef long long ll;
typedef unsigned long long ull;
constexpr int maxn = 100005, inf = 1e9;
std::mt19937 rnd(std::random_device{}() ^ (ull) new char);
int n, k, q, b[maxn];
struct SparseTable {
int c[17][maxn];
void init()
{
memcpy(c[0], b, sizeof b);
for(int i = 1; i < 17; i++) for(int j = 1; j <= n; j++)
c[i][j] = std::min(c[i - 1][j], c[i - 1][j + (1 << i - 1)]);
}
int query(int l, int r)
{
int len = std::__lg(r - l + 1);
return std::min(c[len][l], c[len][r - (1 << len) + 1]);
}
}ST;
struct Treap {
struct node {
int mode, l, r, v, mn, ls, rs, sz, p, c;
}s[maxn << 3];
int rt, cnt;
void newnode(int &k)
{
k = ++cnt;
s[k].mn = inf;
s[k].p = rnd();
}
void pushup(int k)
{
s[k].mn = std::min({s[s[k].ls].mn, s[s[k].rs].mn, s[k].v});
s[k].sz = s[s[k].ls].sz + s[s[k].rs].sz + s[k].c;
}
int merge(int l, int r)
{
if(!l || !r) return l | r;
int ret;
if(s[l].p < s[r].p) s[ret = l].rs = merge(s[l].rs, r);
else s[ret = r].ls = merge(l, s[r].ls);
pushup(ret);
return ret;
}
void erase(int &root, int k)
{
if(root == k) return void(root = merge(s[k].ls, s[k].rs));
erase(s[root].ls, k);
pushup(root);
}
void init()
{
s[0].mn = inf;
for(int i = 1; i <= k; i++)
{
int tmp;
newnode(tmp);
s[tmp].l = 1, s[tmp].r = n;
s[tmp].mn = s[tmp].v = ST.query(1, n);
s[tmp].sz = s[tmp].c = n;
rt = merge(rt, tmp);
}
}
void split_size(int k, int rank, int &l, int &r)
{
if(!k) return void(l = r = 0);
int tmp = s[s[k].ls].sz + s[k].c;
if(tmp <= rank) l = k, split_size(s[k].rs, rank - tmp, s[k].rs, r);
else r = k, split_size(s[k].ls, rank, l, s[k].ls);
pushup(k);
}
int first(int k)
{
while(s[k].ls) k = s[k].ls;
return k;
}
void split(int ql, int qr, int &left, int &mid, int &right)
{
split_size(rt, qr, left, right), split_size(left, ql - 1, left, mid);
int a = first(mid), b = first(right);
if(!a)// -[--|-|--]-
{
erase(right, b);
s[b].ls = s[b].rs = 0;
int tmp;
if(s[b].mode == 0)
{
int l = s[b].l, r = s[b].r;
if(s[left].sz + 1 < ql)
{
newnode(tmp);
s[tmp].l = l, s[tmp].r = ql - 1 - s[left].sz + l - 1;
s[tmp].mn = s[tmp].v = ST.query(l, s[tmp].r);
s[tmp].sz = s[tmp].c = s[tmp].r - l + 1;
left = merge(left, tmp);
l = s[tmp].r + 1;
}
s[b].l = l, s[b].r = qr - s[left].sz + l - 1;
s[b].mn = s[b].v = ST.query(l, s[b].r);
s[b].sz = s[b].c = s[b].r - l + 1;
mid = b;
l = s[b].r + 1;
newnode(tmp);
s[tmp].l = l, s[tmp].r = r;
s[tmp].mn = s[tmp].v = ST.query(l, r);
s[tmp].sz = s[tmp].c = r - l + 1;
right = merge(tmp, right);
}
else
{
int c = s[b].c, v = s[b].v;
if(s[left].sz + 1 < ql)
{
newnode(tmp);
s[tmp].mode = 1;
s[tmp].mn = s[tmp].v = v;
s[tmp].sz = s[tmp].c = ql - s[left].sz - 1;
c -= s[tmp].c;
left = merge(left, tmp);
}
s[b].mn = v;
s[b].sz = s[b].c = qr - ql + 1;
mid = b;
c -= qr - ql + 1;
newnode(tmp);
s[tmp].mode = 1;
s[tmp].mn = s[tmp].v = v;
s[tmp].sz = s[tmp].c = c;
right = merge(tmp, right);
}
return;
}
if(ql == s[left].sz + 1) goto la;
erase(mid, a);
s[a].ls = s[a].rs = 0;
int tmp;
if(s[a].mode == 0)
{
int l = s[a].l, r = s[a].r;
s[a].r = ql - s[left].sz - 1 + l - 1;
s[a].mn = s[a].v = ST.query(l, s[a].r);
s[a].sz = s[a].c = s[a].r - l + 1;
newnode(tmp);
s[tmp].l = s[a].r + 1, s[tmp].r = r;
s[tmp].mn = s[tmp].v = ST.query(s[tmp].l, r);
s[tmp].sz = s[tmp].c = r - s[tmp].l + 1;
}
else
{
int c = s[a].c, v = s[a].v;
s[a].mn = v;
s[a].c = s[a].sz = ql - s[left].sz - 1;
newnode(tmp);
s[tmp].mode = 1;
s[tmp].v = s[tmp].mn = v;
s[tmp].sz = s[tmp].c = c - s[a].c;
}
left = merge(left, a);
mid = merge(tmp, mid);
la:
if(!b || qr == s[left].sz + s[mid].sz) goto lb;
erase(right, b);
s[b].ls = s[b].rs = 0;
if(s[b].mode == 0)
{
int l = s[b].l, r = s[b].r;
s[b].r = qr - s[left].sz - s[mid].sz + l - 1;
s[b].mn = s[b].v = ST.query(l, s[b].r);
s[b].sz = s[b].c = s[b].r - l + 1;
newnode(tmp);
s[tmp].l = s[b].r + 1, s[tmp].r = r;
s[tmp].mn = s[tmp].v = ST.query(s[tmp].l, r);
s[tmp].sz = s[tmp].c = r - s[tmp].l + 1;
}
else
{
int c = s[b].c, v = s[b].v;
s[b].mn = v;
s[b].c = s[b].sz = qr - s[left].sz - s[mid].sz;
newnode(tmp);
s[tmp].mode = 1;
s[tmp].v = s[tmp].mn = v;
s[tmp].sz = s[tmp].c = c - s[b].c;
}
mid = merge(mid, b);
right = merge(tmp, right);
lb:;
}
int query(int ql, int qr)
{
int left, mid, right;
split(ql, qr, left, mid, right);
int ret = s[mid].mn;
rt = merge(merge(left, mid), right);
return ret;
}
void modify(int ql, int qr, int val)
{
int left, mid, right;
split(ql, qr, left, mid, right);
newnode(mid);
s[mid].mode = 1, s[mid].v = s[mid].mn = val;
s[mid].sz = s[mid].c = qr - ql + 1;
rt = merge(merge(left, mid), right);
}
}tree;
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
read(n, k);
for(int i = 1; i <= n; i++) read(b[i]);
ST.init(), tree.init();
read(q);
for(int i = 1, op, l, r, x; i <= q; i++)
{
read(op, l, r);
if(op == 1) read(x), tree.modify(l, r, x);
else printf("%d\n", tree.query(l, r));
}
return 0;
}

浙公网安备 33010602011771号