严格来说,珂朵莉树主要的用处是骗分 ——OI Wiki
class ODT {
struct node {
int l, r;
mutable ll v;
node(const int& il, const int& ir, const ll& iv) : l(il), r(ir), v(iv) {}
inline bool operator<(const node& o) const { return l < o.l; }
};
set<node> odt;
public:
// void init() {
// cin >> n;
// for (int i = 1; i <= n; ++i) {
// int x;
// cin >> x, odt.insert(node(i, i, x));
// }
// }
auto split(int x) {
if (x > n) return odt.end();
auto it = --odt.upper_bound(node(x, 0, 0));
if (it->l == x) return it;
int l = it->l, r = it->r;
ll v = it->v;
odt.erase(it);
odt.insert(node(l, x - 1, v));
return odt.insert(node(x, r, v)).first;
}
void assign(int l, int r, ll v) {
auto itr = split(r + 1), itl = split(l);
odt.erase(itl, itr);
odt.insert(node(l, r, v));
}
void add(int l, int r, ll v) {
auto itr = split(r + 1), itl = split(l);
for (; itl != itr; ++itl) itl->v += v;
}
ll kth_element(int l, int r, int k) {
auto itr = split(r + 1), itl = split(l);
vector<pair<ll, int>> V;
for (; itl != itr; ++itl) V.push_back(make_pair(itl->v, itl->r - itl->l + 1));
sort(V.begin(), V.end());
for (auto x : V) {
k -= x.second;
if (k <= 0) return x.first;
}
return -1;
}
void query(int l, int r) {
auto itr = split(r + 1), itl = split(l);
ll ans = 0;
for (; itl != itr; ++itl) {
// itl->r - itl->l + 1 itl->v
// sum += (itl->r - itl->l + 1) * itl->v;
}
}
};