社区讨论
关于本题复杂度的疑问
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 条回复,欢迎继续交流。
正在加载回复...