[CF1476G] Minimum Difference
不显然不同出现次数的数最多 \(O \left ( \sqrt n \right )\)。
\(\sum\limits_{i=1}^k i = n\)
算出 \(k\) 最大为 \(\sqrt n\)。
则莫队 + 值域分块,维护每个出现次数有几个数。
查询时扫所有块,块内有值就暴力整块,把所有有值的位置提出来,做双指针。
具体一点,设当前双指针的左右端点分别为 \(l, r\)。
不断循环直到 \(\left [ l, r \right ]\) 总的出现次数大于等于 \(k\)。
然后每次把 \(l\) 往后移一位就行。
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
    int f = 0, ans = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        ans = (ans << 3) + (ans << 1) + c - 48, c = getchar();
    return f ? -ans : ans;
}
void write(int x)
{
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
constexpr int N = 1e5 + 5, V = 1e5, inf = 1e9;
int n, m, a[N], res[N];
int blk, l, r, bl[N], mp[N];
struct oper
{
    int p, lst, x;
} op[N];
struct quest
{
    int l, r, k, tim, id;
    bool operator<(const quest &rhs) const
    {
        if (bl[l] != bl[rhs.l])
            return l < rhs.l;
        if (bl[r] != bl[rhs.r])
            return r < rhs.r;
        return tim < rhs.tim;
    }
} q[N];
namespace block
{
    int blk, tot, bl[N], L[N], R[N];
    int t, s[N], cnt[N], cnt_blk[N];
    inline void init()
    {
        blk = pow(V, 2.0 / 3);
        tot = V / blk + (bool)(V % blk);
        for (int i = 1; i <= V; ++i)
            bl[i] = (i - 1) / blk + 1;
        for (int i = 1; i <= tot; ++i)
            L[i] = (i - 1) * blk + 1, R[i] = i * blk;
        R[tot] = V;
    }
    inline void modify(int x, int w) { x ? (cnt[x] += w, cnt_blk[bl[x]] += w) : 0; }
    inline int get_ans(int k)
    {
        t = 0;
        for (int i = 1; i <= tot; ++i)
            if (cnt_blk[i])
                for (int j = L[i]; j <= R[i]; ++j)
                    if (cnt[j])
                        s[++t] = j;
        int ans = inf, sum = 0;
        for (int l = 1, r = 0; l <= t; ++l)
        {
            while (r < t && sum < k)
                sum += cnt[s[++r]];
            if (sum < k)
                break;
            ans = min(ans, s[r] - s[l]);
            sum -= cnt[s[l]];
        }
        return ans;
    }
}
inline void init()
{
    block::init(), blk = pow(n, 2.0 / 3);
    for (int i = 1; i <= n; ++i)
        bl[i] = (i - 1) / blk + 1;
}
inline void insert(int x) { block::modify(mp[x], -1), block::modify(++mp[x], 1); }
inline void remove(int x) { block::modify(mp[x], -1), block::modify(--mp[x], 1); }
inline void insert_in_bound(int i)
{
    if (i >= l && i <= r)
        block::modify(mp[a[i]], -1), block::modify(++mp[a[i]], 1);
}
inline void remove_in_bound(int i)
{
    if (i >= l && i <= r)
        block::modify(mp[a[i]], -1), block::modify(--mp[a[i]], 1);
}
inline void forward(int i)
{
    auto &[p, lst, x] = op[i];
    remove_in_bound(p);
    a[p] = x;
    insert_in_bound(p);
}
inline void backward(int i)
{
    auto &[p, lst, x] = op[i];
    remove_in_bound(p);
    a[p] = lst;
    insert_in_bound(p);
}
signed main()
{
    // freopen("chk.in", "r", stdin);
    // freopen("chk.out", "w", stdout);
    n = read(), m = read();
    for (int i = 1; i <= n; ++i)
        a[i] = read();
    init();
    int que = 0, ti = 0;
    for (int i = 1; i <= m; ++i)
        if (read() == 1)
        {
            ++que, q[que] = {0, 0, 0, ti, que};
            q[que].l = read(), q[que].r = read(), q[que].k = read();
        }
        else
        {
            ++ti;
            op[ti].lst = a[op[ti].p = read()];
            a[op[ti].p] = op[ti].x = read();
        }
    while (ti)
        a[op[ti].p] = op[ti].lst, --ti;
    sort(q + 1, q + que + 1);
    l = 1, r = 0;
    for (int i = 1; i <= que; ++i)
    {
        while (l > q[i].l)
            insert(a[--l]);
        while (r < q[i].r)
            insert(a[++r]);
        while (l < q[i].l)
            remove(a[l++]);
        while (r > q[i].r)
            remove(a[r--]);
        while (ti < q[i].tim)
            forward(++ti);
        while (ti > q[i].tim)
            backward(ti--);
        res[q[i].id] = block::get_ans(q[i].k);
    }
    for (int i = 1; i <= que; ++i)
        write(res[i] == inf ? -1 : res[i]), putchar('\n');
    return 0;
}
 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号