蹲一个有时间的大佬帮忙调树套树qwq

学术版

zhiyangfan @ 2021-08-06 17:38:00

今天模拟赛脑子抽了三维偏序写个树套树,然后爆零了,然后我开始调,然后一下午没了。问了队爷lch他也没找出来错/kk 。麻烦各位有时间的帮忙看一下树套树哪里有问题qwq。

ps 已经用暴力验证过式子没有问题。

#include <cstdio>
#include <algorithm>
const int N = 1e6 + 10;
struct D2_Tree
{
    #define Ls(x) (node[x].son[0])
    #define Rs(x) (node[x].son[1])
    #define Fa(x) (node[x].fa)
    struct Splay{ int fa, son[2], val, size, cnt; }node[N << 2];
    int rt[N << 2], tot;
    void pushup(int x)
    { node[x].size = node[Ls(x)].size + node[Rs(x)].size + node[x].cnt; }
    int get(int x) { return Rs(Fa(x)) == x; }
    void rotate(int x)
    {
        int fa = Fa(x), gf = Fa(fa), d = get(x), dd = get(fa);
        node[fa].son[d] = node[x].son[d ^ 1]; Fa(node[x].son[d ^ 1]) = fa;
        node[x].son[d ^ 1] = fa; Fa(fa) = x; Fa(x) = gf;
        if (gf) node[gf].son[dd] = x;
        pushup(fa); pushup(x);
    }
    void splay(int& root, int x)
    {
        for (int fa; fa = Fa(x); rotate(x))
            if (Fa(fa)) rotate(get(fa) == get(x) ? fa : x);
        root = x;
    }
    void ins(int& root, int val)
    {
        int x = root, fa = 0;
        while (x && node[x].val != val)
        {
            fa = x;
            x = node[x].son[node[x].val < val];
        }
        if (x) node[x].cnt++, ++node[x].size;
        else
        {
            node[x = ++tot].val = val; node[x].fa = fa;
            node[x].size = node[x].cnt = 1;
            Ls(x) = Rs(x) = 0; 
        }
        splay(root, x);
    }
    int get_rank(int& root, int val)
    {
        int x = root, rk = 0;
        while (x)
        {
            if (node[x].val > val) x = Ls(x);
            else if (node[x].val == val)
            {
                rk += node[Ls(x)].size; 
                splay(root, x); return rk;
            }
            else rk += node[Ls(x)].size + node[x].cnt, x = Rs(x);
        }
        return rk;
    }
    int get_cnt(int& root, int val)
    {
        int x = root;
        while (x)
        {
            if (node[x].val > val) x = Ls(x);
            else if (node[x].val == val) 
            { splay(root, x); return node[x].cnt; }
            else x = Rs(x);
        }
        return 0;
    }
    void add(int k, int l, int r, int x, int v)
    {
        ins(rt[k], v);
        if (l == r) return ;
        int mid = l + r >> 1;
        if (x <= mid) add(k << 1, l, mid, x, v);
        else add(k << 1 | 1, mid + 1, r, x, v);
    }
    int query_rank(int k, int l, int r, int x, int y, int v)
    {
        if (x <= l && r <= y) return get_rank(rt[k], v);
        int mid = l + r >> 1, ret = 0;
        if (x <= mid) ret += query_rank(k << 1, l, mid, x, y, v);
        if (mid < y) ret += query_rank(k << 1 | 1, mid + 1, r, x, y, v);
        return ret;
    }
    int query_cnt(int k, int l, int r, int x, int y, int v)
    {
        if (x <= l && r <= y) return get_cnt(rt[k], v);
        int mid = l + r >> 1, ret = 0;
        if (x <= mid) ret += query_cnt(k << 1, l, mid, x, y, v);
        if (mid < y) ret += query_cnt(k << 1 | 1, mid + 1, r, x, y, v);
        return ret;
    }
    #undef Ls
    #undef Rs
    #undef Fa
}tree1, tree2;
struct Q{ int l, r, typ, t, pos; }q[N];
int tmp[N << 2], tp, eid;
inline int getid(int val)
{
    int l = 1, r = eid, mid;
    while (l < r)
    {
        mid = l + r >> 1;
        if (tmp[mid] == val) return mid;
        if (tmp[mid] < val) l = mid + 1;
        else r = mid - 1;
    }
    return l;
}
int main()
{
    freopen("mind.in", "r", stdin); freopen("mind.out", "w", stdout);
    int n; scanf("%d", &n); char opt[5];
    for (int i = 1; i <= n; i++)
    {
        scanf("%s%d", opt, &q[i].pos);
        if (opt[0] == 'T')
            scanf("%d", &q[i].t), q[i].typ = 1,
            tmp[++tp] = q[i].pos, tmp[++tp] = q[i].pos - q[i].t, tmp[++tp] = q[i].pos + q[i].t;
        else
        {
            scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].t); q[i].typ = 2; 
            tmp[++tp] = q[i].pos - q[i].t; tmp[++tp] = q[i].pos + q[i].t;
            tmp[++tp] = q[i].l; tmp[++tp] = q[i].r;
        }
    }
    std::sort(tmp + 1, tmp + 1 + tp);
    eid = std::unique(tmp + 1, tmp + tp + 1) - tmp - 1;
    for (int i = 1, l, r, pos, t1, t2, t3; i <= n; i++)
    {
        if (q[i].typ == 1)
        {           
            pos = getid(q[i].pos);
            tree1.add(1, 1, eid, pos, getid(q[i].pos - q[i].t));
            tree2.add(1, 1, eid, pos, getid(q[i].pos + q[i].t));
        }
        else 
        {
            l = getid(q[i].l), r = getid(q[i].r); 
            printf("%d\n", -tree2.query_rank(1, 1, eid, l, r, getid(q[i].pos - q[i].t)) + 
            tree1.query_rank(1, 1, eid, l, r, getid(q[i].pos + q[i].t)) +
            tree1.query_cnt(1, 1, eid, l, r, getid(q[i].pos + q[i].t)));
        }
    }
    return 0;
}

by zhiyangfan @ 2021-08-06 18:19:29

有没有其他的方法来做的这个三维偏序啊/kel

大概是

\begin{cases}l\le pos_0 \le r \\ pos_0-t_0>pos_1+t_1\\pos_0+t_0<pos_1-t_1\end{cases}

如果有大佬需要原题我马上放/kel


|