社区讨论

关于本题复杂度的疑问

P5350序列参与者 3已保存回复 6

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
6 条
当前快照
1 份
快照标识符
@lo36yoj4
此快照首次捕获于
2023/10/24 01:48
2 年前
此快照最后确认于
2023/10/24 01:48
2 年前
查看原帖
为什么复制直接复制不会出问题?难道一个深度较大的树复制到深度较小的树不会使树的深度增加吗?多次重复这样的操作不是就寄了吗?
CPP
// This Code was made by Chinese_zjc_.
#include <bits/stdc++.h>
// #define debug
unsigned long long seed = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937 Rand(seed);
const int MOD = 1000000007;
struct mint
{
    unsigned v;
    mint(unsigned v_ = 0) : v(v_) {}
    mint operator-() const { return v ? MOD - v : *this; }
    mint &operator+=(const mint &X) { return (v += X.v) >= MOD ? v -= MOD : v, *this; }
    mint &operator-=(const mint &X) { return (v += MOD - X.v) >= MOD ? v -= MOD : v, *this; }
    mint &operator*=(const mint &X) { return v = 1llu * v * X.v % MOD, *this; }
    mint &operator/=(const mint &X) { return *this *= X.inv(); }
    mint pow(long long B) const
    {
        B %= MOD - 1;
        if (B < 0)
            B += MOD - 1;
        mint res = 1, A = *this;
        while (B)
        {
            if (B & 1)
                res *= A;
            B >>= 1;
            A *= A;
        }
        return res;
    }
    mint inv() const { return pow(MOD - 2); }
    friend mint operator+(const mint &A, const mint &B) { return mint(A) += B; }
    friend mint operator-(const mint &A, const mint &B) { return mint(A) -= B; }
    friend mint operator*(const mint &A, const mint &B) { return mint(A) *= B; }
    friend mint operator/(const mint &A, const mint &B) { return mint(A) /= B; }
    friend std::istream &operator>>(std::istream &A, mint &B) { return A >> B.v; }
    friend std::ostream &operator<<(std::ostream &A, const mint &B) { return A << B.v; }
    friend bool operator==(const mint &A, const mint &B) { return A.v == B.v; }
    explicit operator bool() const { return v; }
};
struct ltag
{
    bool rev, fill;
    mint val;
    ltag() : rev(), fill(), val() {}
    ltag(bool rev_, bool fill_, mint val_) : rev(rev_), fill(fill_), val(val_) {}
    ltag &operator+=(const ltag &X)
    {
        rev ^= X.rev;
        if (X.fill)
        {
            fill = true;
            val = X.val;
        }
        else
            val += X.val;
        return *this;
    }
};
template <class node>
struct ss
{
    node *to;
    unsigned *ti;
    ss() : to(), ti() {}
    ss(node *x) : to(x), ti(new unsigned(1)) {}
    ss(const ss &x) : to(x.to), ti(x.ti) { ti && ++*ti; }
    ss &operator=(const ss &x)
    {
        ti && !--*ti ? delete ti, delete to : void();
        to = x.to;
        (ti = x.ti) ? ++*ti : 0;
        return *this;
    }
    ~ss() { ti && !--*ti && (delete ti, delete to, 0); }
    void reset(node *x) { *this = ss(x); }
    operator bool() const { return to; }
    node *operator->() const { return to; }
    node &operator*() const { return *to; }
};
struct node
{
    unsigned w, siz;
    ss<node> lson, rson;
    mint sum, val;
    ltag tag;
    node(mint val_ = 0) : w(Rand()), siz(1), lson(), rson(), sum(val_), val(val_), tag() {}
    friend unsigned size(const ss<node> &X) { return X ? X->siz : 0; }
    void pushup()
    {
        sum = (lson ? lson->sum : 0) + val + (rson ? rson->sum : 0);
        siz = (lson ? lson->siz : 0) + 1 + (rson ? rson->siz : 0);
    }
    void pushdown()
    {
        if (tag.rev || tag.fill || tag.val)
        {
            if (lson)
            {
                node *res = new node(*lson);
                *res += tag;
                lson.reset(res);
            }
            if (rson)
            {
                node *res = new node(*rson);
                *res += tag;
                rson.reset(res);
            }
            tag = ltag();
        }
    }
    node &operator+=(const ltag &X)
    {
        if (X.fill)
        {
            sum = siz * X.val;
            val = X.val;
        }
        else
        {
            sum += siz * X.val;
            val += X.val;
        }
        if (X.rev)
            std::swap(lson, rson);
        tag += X;
        return *this;
    }
};
struct treap
{
    ss<node> root;
    ss<node> merge(ss<node> A, ss<node> B)
    {
        if (!A)
            return B;
        if (!B)
            return A;
        if (A->w < B->w)
        {
            A.reset(new node(*A));
            A->pushdown();
            A->rson = merge(A->rson, B);
            A->pushup();
            return A;
        }
        else
        {
            B.reset(new node(*B));
            B->pushdown();
            B->lson = merge(A, B->lson);
            B->pushup();
            return B;
        }
    }
    std::pair<ss<node>, ss<node>> split(ss<node> X, unsigned len)
    {
        if (!X)
            return {};
        X.reset(new node(*X));
        X->pushdown();
        if (size(X->lson) < len)
        {
            std::pair<ss<node>, ss<node>> res = split(X->rson, len - size(X->lson) - 1);
            X->rson = res.first;
            res.first = X;
            X->pushup();
            return res;
        }
        else
        {
            std::pair<ss<node>, ss<node>> res = split(X->lson, len);
            X->lson = res.second;
            res.second = X;
            X->pushup();
            return res;
        }
    }
    void addnode(mint val)
    {
        node *tmp = new node(val);
        root = merge(root, ss<node>(tmp));
    }
    void add(int l, int r, mint v)
    {
        std::pair<ss<node>, ss<node>> R = split(root, r),
                                      L = split(R.first, l);
        ss<node> tmp(new node(*L.second));
        *tmp += ltag(false, false, v);
        root = merge(merge(L.first, tmp), R.second);
    }
    void fill(int l, int r, mint v)
    {
        std::pair<ss<node>, ss<node>> R = split(root, r),
                                      L = split(R.first, l);
        ss<node> tmp(new node(*L.second));
        *tmp += ltag(false, true, v);
        root = merge(merge(L.first, tmp), R.second);
    }
    void reverse(int l, int r)
    {
        std::pair<ss<node>, ss<node>> R = split(root, r),
                                      L = split(R.first, l);
        ss<node> tmp(new node(*L.second));
        *tmp += ltag(true, false, 0);
        root = merge(merge(L.first, tmp), R.second);
    }
    mint query(int l, int r)
    {
        std::pair<ss<node>, ss<node>> R = split(root, r),
                                      L = split(R.first, l);
        mint res = L.second->sum;
        root = merge(merge(L.first, L.second), R.second);
        return res;
    }
    void swap(int l1, int r1, int l2, int r2)
    {
        if (l1 > l2)
            std::swap(l1, l2), std::swap(r1, r2);
        std::pair<ss<node>, ss<node>> R2 = split(root, r2),
                                      L2 = split(R2.first, l2),
                                      R1 = split(L2.first, r1),
                                      L1 = split(R1.first, l1);
        std::swap(L1.second, L2.second);
        root = merge(merge(merge(merge(L1.first, L1.second), R1.second), L2.second), R2.second);
    }
    void copy(int l1, int r1, int l2, int r2)
    {
        bool rev = l1 > l2;
        if (rev)
            std::swap(l1, l2), std::swap(r1, r2);
        std::pair<ss<node>, ss<node>> R2 = split(root, r2),
                                      L2 = split(R2.first, l2),
                                      R1 = split(L2.first, r1),
                                      L1 = split(R1.first, l1);
        if (rev)
            L1.second = L2.second;
        else
            L2.second = L1.second;
        root = merge(merge(merge(merge(L1.first, L1.second), R1.second), L2.second), R2.second);
    }
    void visit(ss<node> cur, int dep = 0)
    {
        if (!cur)
            return;
        cur->pushdown();
        // if (cur->lson)
        //     std::cout << cur.to << ' ' << cur->lson.to << std::endl;
        visit(cur->lson, dep + 1);
        std::cout << cur->val << ',' << dep << ' ';
        // if (cur->rson)
        //     std::cout << cur.to << ' ' << cur->rson.to << std::endl;
        visit(cur->rson, dep + 1);
    }
} T;
int n, m;
signed main()
{
    std::ios::sync_with_stdio(false);
    // std::cin.tie(nullptr);
    std::cin >> n >> m;
    for (int i = 0, x; i != n; ++i)
    {
        std::cin >> x;
        T.addnode(x);
    }
    for (int i = 0, opt, l, r, l1, r1, l2, r2, x; i != m; ++i)
    {
        std::cin >> opt;
        switch (opt)
        {
        case 1:
            std::cin >> l >> r;
            std::cout << T.query(--l, r) << std::endl;
            break;
        case 2:
            std::cin >> l >> r >> x;
            T.fill(--l, r, x);
            break;
        case 3:
            std::cin >> l >> r >> x;
            T.add(--l, r, x);
            break;
        case 4:
            std::cin >> l1 >> r1 >> l2 >> r2;
            T.copy(--l1, r1, --l2, r2);
            break;
        case 5:
            std::cin >> l1 >> r1 >> l2 >> r2;
            T.swap(--l1, r1, --l2, r2);
            break;
        case 6:
            std::cin >> l >> r;
            T.reverse(--l, r);
            break;
        }
    }
    T.visit(T.root);
    std::cout << std::endl;
    return 0;
}

回复

6 条回复,欢迎继续交流。

正在加载回复...