FHQ求助卡常,#2 2.2s TLE
查看原帖
FHQ求助卡常,#2 2.2s TLE
576378
creation_hy楼主2022/10/12 20:16

是我写假了吗

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e4 + 5;
const int MAXM = 1e7 + 5;
const int INF = 2147483647;
int n, m, a[MAXN];
inline int read()
{
    int s = 0, f = 1;
    char ch = getchar();
    while (ch < 48 || ch > 57)
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= 48 && ch <= 57)
    {
        s = (s << 3) + (s << 1) + (ch ^ 48);
        ch = getchar();
    }
    return s * f;
}
namespace FHQ
{
    int ch[MAXM][2], pri[MAXM], sz[MAXM], val[MAXM], tot = 0;
    // --- bottom ---
    inline int Add(int x)
    {
        val[++tot] = x;
        pri[tot] = rand();
        sz[tot] = 1;
        return tot;
    }
    inline void push_up(int x)
    {
        sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;
    }
    int Merge(int x, int y)
    {
        if (!x || !y)
            return x + y;
        if (pri[x] < pri[y])
        {
            ch[x][1] = Merge(ch[x][1], y);
            push_up(x);
            return x;
        }
        else
        {
            ch[y][0] = Merge(x, ch[y][0]);
            push_up(y);
            return y;
        }
    }
    void Split(int cur, int k, int &x, int &y)
    {
        if (!cur)
        {
            x = y = 0;
            return;
        }
        if (val[cur] <= k)
        {
            x = cur;
            Split(ch[cur][1], k, ch[cur][1], y);
        }
        else
        {
            y = cur;
            Split(ch[cur][0], k, x, ch[cur][0]);
        }
        push_up(cur);
    }
    int Find(int cur, int k)
    {
        while (true)
            if (sz[ch[cur][0]] >= k)
                cur = ch[cur][0];
            else if (sz[ch[cur][0]] + 1 == k)
                return cur;
            else
            {
                k -= sz[ch[cur][0]] + 1;
                cur = ch[cur][1];
            }
    }
    // --- application ---
    inline void Insert(int &root, int k)
    {
        int x, y;
        Split(root, k, x, y);
        root = Merge(x, Merge(Add(k), y));
    }
    inline void Delete(int &root, int k)
    {
        int x, y, z;
        Split(root, k, x, z);
        Split(x, k - 1, x, y);
        y = Merge(ch[y][0], ch[y][1]);
        root = Merge(x, Merge(y, z));
    }
    inline int Rank(int root, int k)
    {
        int x, y;
        Split(root, k - 1, x, y);
        int ans = sz[x] + 1;
        root = Merge(x, y);
        return ans;
    }
    inline int Last(int root, int k)
    {
        int x, y;
        Split(root, k - 1, x, y);
        int ans = sz[x] ? val[Find(x, sz[x])] : -INF;
        root = Merge(x, y);
        return ans;
    }
    inline int Next(int root, int k)
    {
        int x, y;
        Split(root, k, x, y);
        int ans = sz[y] ? val[Find(y, 1)] : INF;
        root = Merge(x, y);
        return ans;
    }
    // --- level 2 application ---
    inline void build(int &root, int l, int r)
    {
        for (int i = l; i <= r; i++)
            Insert(root, a[i]);
    }
}
namespace SegTree
{
    int t[MAXN << 2], root[MAXN << 2];
    inline int ls(int p)
    {
        return p << 1;
    }
    inline int rs(int p)
    {
        return p << 1 | 1;
    }
    void build(int p, int l, int r)
    {
        FHQ::build(root[p], l, r);
        if (l == r)
            return;
        int mid = l + r >> 1;
        build(ls(p), l, mid);
        build(rs(p), mid + 1, r);
    }
    void update(int p, int l, int r, int pre, int k)
    {
        FHQ::Delete(root[p], a[pre]);
        FHQ::Insert(root[p], k);
        if (l == r)
            return;
        int mid = l + r >> 1;
        if (pre <= mid)
            update(ls(p), l, mid, pre, k);
        else
            update(rs(p), mid + 1, r, pre, k);
    }
    int Rank(int p, int qx, int qy, int l, int r, int k)
    {
        if (qx > r || qy < l)
            return 0;
        if (qx <= l && r <= qy)
            return FHQ::Rank(root[p], k) - 1;
        int mid = l + r >> 1;
        return Rank(ls(p), qx, qy, l, mid, k) + Rank(rs(p), qx, qy, mid + 1, r, k);
    }
    int Find(int l, int r, int k)
    {
        int x = 0, y = 1e8;
        while (x <= y)
        {
            int mid = x + y >> 1;
            if (Rank(1, l, r, 1, n, mid) + 1 <= k)
                x = mid + 1;
            else
                y = mid - 1;
        }
        return x - 1;
    }
    int Last(int p, int qx, int qy, int l, int r, int k)
    {
        if (qx > r || qy < l)
            return -INF;
        if (qx <= l && r <= qy)
            return FHQ::Last(root[p], k);
        int mid = l + r >> 1;
        return max(Last(ls(p), qx, qy, l, mid, k), Last(rs(p), qx, qy, mid + 1, r, k));
    }
    int Next(int p, int qx, int qy, int l, int r, int k)
    {
        if (qx > r || qy < l)
            return INF;
        if (qx <= l && r <= qy)
            return FHQ::Next(root[p], k);
        int mid = l + r >> 1;
        return min(Next(ls(p), qx, qy, l, mid, k), Next(rs(p), qx, qy, mid + 1, r, k));
    }
}
int main()
{
    // ios::sync_with_stdio(false);
    // cin.tie(nullptr);
    // freopen("t.in", "r", stdin);
    n = read();
    m = read();
    for (int i = 1; i <= n; i++)
        a[i] = read();
    SegTree::build(1, 1, n);
    int op, x, y, z;
    while (m--)
    {
        op = read();
        x = read();
        y = read();
        if (op == 3)
        {
            SegTree::update(1, 1, n, x, y);
            a[x] = y;
            continue;
        }
        z = read();
        switch (op)
        {
        case 1:
            printf("%d\n", SegTree::Rank(1, x, y, 1, n, z) + 1);
            break;
        case 2:
            printf("%d\n", SegTree::Find(x, y, z));
            break;
        case 4:
            printf("%d\n", SegTree::Last(1, x, y, 1, n, z));
            break;
        default:
            printf("%d\n", SegTree::Next(1, x, y, 1, n, z));
        }
    }
    return 0;
}

我看题解区有人写FHQ的啊,,

2022/10/12 20:16
加载中...