• 其他-一大堆记录 (20 Dec


    我好菜啊 Orz

    数据结构

    平衡树

    代码对应 LOJ104 普通平衡树

    Scapegoat Tree

    #include <cstdio>
    #include <ctype.h>
    #include <algorithm>
    
    using namespace std;
    
    const int _N = 101000;
    
    char *p1, *p2, buf[1 << 20];
    
    inline char gc()
    {
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin)) == p1 ? EOF : *p1++;
    }
    
    template<typename T>
    void rd(T &num)
    {
        char tt;
        bool flag;
        while (!isdigit(tt = gc()) && tt != '-');
        if (tt == '-')
            num = 0, flag = 1;
        else
            num = tt - '0', flag = 0;
        while (isdigit(tt = gc()))
            num = num * 10 + tt - '0';
        if (flag)
            num = -num;
        return;
    }
    
    namespace goat {
    
        struct node {
            node *l, *r;
            int v, siz, cnt, exi;
        } GT[_N], *Tl, *Rt, *Lun, *MPL[_N];
    
        int MPL_cnt, Tmp_cnt, Tmp_v[_N], Tmp_exi[_N];
        double Alpha = 0.6666;
    
        void init()
        {
            Rt = Tl = Lun = GT;
            Lun->l = Lun->r = Lun;
            Lun->v = Lun->siz = Lun->cnt = Lun->exi = 0;
            MPL_cnt = 0;
            return;
        }
    
        void mpl_new(node *&p, int x, int exi)
        {
            p = MPL_cnt ? MPL[MPL_cnt--] : ++Tl;
            p->l = p->r = Lun;
            p->v = x;
            p->cnt = 1;
            p->siz = p->exi = exi;
            return;
        }
    
        void rake(node *&p)
        {
            if (p == Lun)
                return;
            rake(p->l);
            MPL[++MPL_cnt] = p;
            if (p->exi)
                Tmp_v[++Tmp_cnt] = p->v, Tmp_exi[Tmp_cnt] = p->exi;
            rake(p->r);
            return;
        }
    
        void maint(node *&p)
        {
            p->siz = p->l->siz + p->r->siz + p->exi;
            p->cnt = p->l->cnt + p->r->cnt + 1;
            return;
        }
        
        void build(node *&p, int l, int r)
        {
            if (l > r)
                return;
            int mid = l + r >> 1;
            mpl_new(p, Tmp_v[mid], Tmp_exi[mid]);
            build(p->l, l, mid - 1), build(p->r, mid + 1, r);
            maint(p);
            return;
        }
        
        void ins(node *&p, int x)
        {
            if (p == Lun) {
                mpl_new(p, x, 1);
                return;
            }
            if (p->v == x)
                ++p->exi;
            else if (p->v > x)
                ins(p->l, x);
            else
                ins(p->r, x);
            
            if (p->l->cnt > Alpha * p->cnt || p->r->cnt > Alpha * p->cnt) {
                Tmp_cnt = 0, rake(p);
                build(p, 1, Tmp_cnt);
            }
    
            maint(p);
            return;
        }
    
        void del(node *&p, int x)
        {
            if (p == Lun) {
                return;
            }
            if (p->v == x && p->exi)
                --p->exi;
            else if (p->v > x)
                del(p->l, x);
            else
                del(p->r, x);
            maint(p);
            return;
        }
    
        int get_rank(node *p, int x)
        {
            int t = 1;
            while (p != Lun) {
                if (p->v >= x)
                    p = p->l;
                else
                    t += p->l->siz + p->exi, p = p->r;
            }
            return t;
        }
    
        int get_kth(node *p, int x)
        {
            while (p != Lun) {
                if (p->l->siz < x && p->l->siz + p->exi >= x)
                    return p->v;
                if (p->l->siz >= x)
                    p = p->l;
                else
                    x -= p->l->siz + p->exi, p = p->r;
            }
            return -1;
        }
    
    }
    
    using namespace goat;
    
    int N;
    
    int main()
    {
        
        rd(N);
        init();
        for (int i = 1; i <= N; ++i) {
            int opt, x;
            rd(opt), rd(x);
            if (opt == 1)
                ins(Rt, x);
            else if (opt == 2)
                del(Rt, x);
            else if (opt == 3)
                printf("%d
    ", get_rank(Rt, x));
            else if (opt == 4)
                printf("%d
    ", get_kth(Rt, x));
            else if (opt == 5)
                printf("%d
    ", get_kth(Rt, get_rank(Rt, x) - 1));
            else if (opt == 6)
                printf("%d
    ", get_kth(Rt, get_rank(Rt, x + 1)));
        }
        return 0;
    }
    

    Treap

    Splay

    FHQ Treap

    树套树

    动态 DP

    序列问题(比如区间最大连续和,历史最大值……)往往直接构造状态就可以了,不过用矩阵可能更好想。

    树上问题的时候,矩阵才真正发挥作用、虽然有大佬可以观察状态,考虑修改对状态的影响,然后在树剖的线段树上二分最后影响位置,但这样思考太费劲了。直接用矩阵转移就可以了。

    这类题代码量特别大,对我这种骨质疏松选手极不友善,所以必须确保头脑清醒再敲代码。

    BZOJ4712 洪水

    定义这种矩阵乘法:

    [C_{i,j}=min{ A_{i,k}+B_{k,j}} ]

    发现满足结合律。(f) 表示子树最小代价, (g) 表示轻儿子的 (f) 之和, (v) 表示权值。
    从儿子 (x) 向父亲 (y) 转移:

    [ egin{bmatrix} f(x) & 0\ end{bmatrix} imes egin{bmatrix} g(y) & infty\ v(y) & 0\ end{bmatrix} = egin{bmatrix} f(y) & 0\ end{bmatrix} ]

    树剖,线段树。注意,一些转移的 (2 imes 2) 矩阵乘起来之后仍然只有两个有意义的元素,所以可以只记录这两个元素。而且这时候会发现,化成最简(大概是那个意思吧)的矩阵转移与一些非常绕的直接 DP 转移做法完全一致。

    对于修改操作,只影响重链顶端节点的父亲的(也就是上一个重链底端) (g) 。无法直接改,需要计算当前链顶端修改后的增量,然后贡献给父亲。

    点分治

    • 找重心,这个过程是 (O(nlog n)) 的。

    • 边分治很好,当需要在一堆里面匹配另一堆已有的数据时,因为一共只有两堆。不过边分治需要补成二叉树,否则菊花图就可以卡掉。 如果树并不能随便加点,那就不能边分了。还没有写过。

    • 动态点分治也还没写。

    prufer 序列

    • Cayley 公式

    • 带编号、度数有限制的无根树计数。

    卷积

    • 多项式乘法原理, (C_k = sum A_xB_{k-x}) 类型的卷积

    • Dirichlet 卷积

    [f(n)igotimes g(n)=h(n)\ h(n) = sum_{d|n}f(d)cdot g(n/d)]

    容斥原理

    • 一般的容斥
    • min-max 容斥

    矩阵

    结合律

    找随机的 (P) ,乘到两边来验证 (A cdot B = C) 是否成立。为什么有解(即出错)概率是数字范围分之一,我不懂啊!

    ((A cdot B)^n = A cdot (B cdot A)^{n-1} cdot B) 有时候会有点用。

    多次询问求 (A^n) 的问题,预处理倍增数组之后可以把每次询问的 (O(k^3log n)) 降到 (O(k^2log n)) ,因为矩阵乘法变成了加法。

    行列式

    真的不懂啊,不过背下来吧。

    多项式

    • 特征多项式
    • 生成函数
  • 相关阅读:
    *** 疑问
    *** C++动态绑定(多态)example code 1
    *** C++纯虚函数使用example code 1
    *** C++实现string各类运算符重载成员函数
    *** C++虚函数表原理相关代码
    *** 自写MyString类:重载操作符 '+'
    *** [转]C++在类的成员函数中,允许直接访问该类的成员对象的私有成员变量
    *** [转] C++基础篇--overload重载&override覆盖&overwrite隐藏
    *** C++ 中的函数重载
    *** 关于虚函数的一些常见问题
  • 原文地址:https://www.cnblogs.com/ghcred/p/10091315.html
Copyright © 2020-2023  润新知