Black Box题解

Black Box题解

题目

题意

有以下两种操作:
a d d ( x ) add(x) : 把 x x 存入
g e t : i + + get: i++ ,然后输出第 i i 小的数
现在给你一个长为 M M a d d add 操作序列 A A N N 个时间点序列 B B ,要求在每个 B i B_i 时执行一次 g e t get 操作,求输出结果序列

思路

直接按照要求在第 i i 个时刻插入一个 a i a_i
然后在每个时刻判断是否到了 B i B_i 的时间
若是到了,便直接查询第 t o t tot 个数,然后 + + t o t ++tot

注意事项

B i B_i 的时候用 w h i l e while
不一定每个查询都在不同时间

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#define pk putchar(' ')
#define ph puts("")
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
template <class T>
void rd(T &x)
{
    x = 0;
    int f = 1;
    char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    x *= f;
}
template <class T>
void pt(T x)
{
    if (x < 0)
        putchar('-'), x = (~x) + 1;
    if (x > 9)
        pt(x / 10);
    putchar(x % 10 ^ 48);
}
template <class T>
T Max(T a, T b)
{
    return a > b ? a : b;
}
template <class T>
T Min(T a, T b)
{
    return a < b ? a : b;
}
using namespace std;
const int INF = 0x3f3f3f3f, N = 1e6 + 5;
int root, ans;
struct node
{
    int l, r, v, num, size;
    ll rnd;
};
//用结构体存变量:
// l:左孩子,r:右孩子;
// v:该节点的权值;
// num:与该节点权值相同的点的个数;
// size:以该节点为根的子树的节点数;
// rnd:该节点的随机值;
// vo:该节点优先级
struct Treap
{
    node t[N];
    int tot;
    void update(int p) 
    {
        t[p].size = t[t[p].r].size + t[t[p].l].size + t[p].num; 
    }
    //用子节点的值更新父节点的值;
    void rt(int &p) 
    {
        int q = t[p].l;
        t[p].l = t[q].r;
        t[q].r = p;
        t[q].size = t[p].size;
        update(p);
        p = q;
    }
    void lt(int &p) 
    {
        int q = t[p].r;
        t[p].r = t[q].l;
        t[q].l = p;
        t[q].size = t[p].size;
        update(p);
        p = q;
    }  
    //基础的左旋右旋操作;
    void ins(int &p, int x) 
    {
        if (!p) 
        {
            p = ++tot;
            t[p].size = t[p].num = 1;
            t[p].v = x;
            t[p].rnd = rand();
            return;
        }
        t[p].size++;
        if (t[p].v == x)
            t[p].num++;
        else if (x > t[p].v) 
        {
            ins(t[p].r, x);
            if (t[t[p].r].rnd < t[p].rnd)
                lt(p);
        }
        //如果要插入的值比当前节点的值大,就将其插入右子树中,同时如果右节点的随机值比当前节点随机值小
        //就要通过左旋来维护堆的性质;
        else 
        {
            ins(t[p].l, x);
            if (t[t[p].l].rnd < t[p].rnd)
                rt(p);
        }//理由同上;
    }
    //删除元素
    void del(int &p, int x)
    {
        if (!p) 
            return;
        if (t[p].v == x)
        {
            if (t[p].num > 1) 
                t[p].num--, t[p].size--;
            else
            {
                if (t[p].l == 0 || t[p].r == 0) 
                    p = t[p].l + t[p].r;
                else if (t[t[p].l].rnd < t[t[p].r].rnd) 
                    rt(p), del(p,x);
                else 
                    lt(p), del(p,x); 
            }
        }
        else if (x > t[p].v) 
            t[p].size--, del(t[p].r, x);
        else 
            t[p].size--, del(t[p].l, x);
    }
    //插入操作
    int fpre(int p, int x) 
    {
        if (!p)
            return -INF;
        if (t[p].v >= x)
            return fpre(t[p].l, x);
        else
            return Max(t[p].v, fpre(t[p].r, x));
    }  
    //查找前驱;
    int fbac(int p, int x) 
    {
        if (!p)
            return INF;
        if (t[p].v <= x)
            return fbac(t[p].r, x);
        else
            return Min(t[p].v, fbac(t[p].l, x));
    }
    //查找后继;
    int fkey(int p, int x)
    {
        if (!p) 
            return 0;
        if (t[p].v == x) 
            return t[t[p].l].size + 1;
        if (x > t[p].v) 
            return t[t[p].l].size + t[p].num + fkey(t[p].r, x);
        else 
            return fkey(t[p].l, x);
    }
    //查询x数的排名;
    int fkth(int p, int x)
    {
        if (!p) 
            return 0;
        if (x <= t[t[p].l].size) 
            return fkth(t[p].l, x);
        x -= t[t[p].l].size;
        if (x <= t[p].num) 
            return t[p].v;
        x -= t[p].num;
        return fkth(t[p].r, x);
    }
    //查询排名为x的数;
}Treap1;
const int M = 3e4 + 5;
int a[M], b[M], m, n, cnt, x;
int main() 
{
    // freopen("testdata.in", "r", stdin);
    // freopen("test.out", "w", stdout);
    srand(*new unsigned);
    rd(m), rd(n);
    for (int i = 1;i <= m; i++)
        rd(a[i]);
    for (int i = 1;i <= n; i++)
        rd(b[i]);
    x = 1;
    for (int i = 1;i <= m; i++)
    {
        Treap1.ins(root, a[i]);
        while (b[x] == i)
        {
            x++;
            pt(Treap1.fkth(root, ++cnt));
            ph;
        } 
    }
    return 0;
}

Thanks!

原创文章 23 获赞 41 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43537070/article/details/103275854