1+ #include < bits/stdc++.h> // SCNUOJ1731 https://oj.socoding.cn/p/1731
2+ using namespace std ;
3+ #define sc (x ) scanf(" %lld" , &x)
4+ typedef long long ll;
5+ ll n;
6+ struct node_t
7+ {
8+ ll l, r;
9+ mutable ll v; // mutable使得const可变(set元素是const)
10+ node_t (const ll &il, const ll &ir, const ll &iv) : l(il), r(ir), v(iv) {}
11+ inline bool operator <(const node_t &o) const { return l < o.l ; }
12+ };
13+ set<node_t > odt; // 建立一棵珂朵莉树
14+ auto split (ll x) // 珂朵莉基操
15+ {
16+ if (x > n)
17+ return odt.end ();
18+ auto it = --odt.upper_bound (node_t {x, 0 , 0 });
19+ if (it->l == x)
20+ return it;
21+ ll l = it->l , r = it->r , v = it->v ;
22+ odt.erase (it);
23+ odt.insert (node_t (l, x - 1 , v));
24+ return odt.insert (node_t (x, r, v)).first ;
25+ }
26+ void assign (ll l, ll r, ll v) // 区间赋值为v, 均摊O(loglogn)
27+ {
28+ auto itr = split (r + 1 ), itl = split (l);
29+ odt.erase (itl, itr);
30+ odt.insert (node_t (l, r, v));
31+ }
32+ void add (ll l, ll r, ll v) // 区间增加v, 均摊O(loglogn)
33+ {
34+ auto itr = split (r + 1 ), itl = split (l);
35+ for (; itl != itr; ++itl) // 枚举每个子区间
36+ {
37+ itl->v = itl->v + v;
38+ }
39+ }
40+ ll query (ll l, ll r) // 区间查询, 均摊O(loglogn)
41+ {
42+ ll res = 0 ;
43+ auto itr = split (r + 1 ), itl = split (l);
44+ for (; itl != itr; ++itl)
45+ { // itl->l, itl->r, itl->v 是当前子区间的左右端点和值
46+ res += (itl->r - itl->l + 1 ) * (itl->v );
47+ }
48+ return res;
49+ }
50+ signed main ()
51+ {
52+ sc (n);
53+ odt.insert ({1 , n, 1236895 }); // 初始化区间
54+ ll m, cmd, l, r, x;
55+ for (sc (m); m--;)
56+ {
57+ sc (cmd), sc (l), sc (r);
58+ if (cmd == 1 )
59+ {
60+ sc (x), assign (l, r, x);
61+ }
62+ else if (cmd == 2 )
63+ {
64+ sc (x), add (l, r, x);
65+ }
66+ else
67+ {
68+ printf (" %lld\n " , query (l, r));
69+ }
70+ }
71+ return 0 ;
72+ }
0 commit comments