Advertisement
Guest User

Untitled

a guest
Nov 22nd, 2019
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.60 KB | None | 0 0
  1. // MuMonash
  2.  
  3. #include <iostream>
  4. #include <vector>
  5.  
  6. using namespace std;
  7.  
  8. typedef vector<int> vi;
  9. typedef long long ll;
  10.  
  11. ll gcd(ll a, ll b) {
  12. if (b==0) { return (a<0) ? -a: a; }
  13. else { return gcd(b, a%b); }
  14. }
  15.  
  16. // Static RMQ (Sparse Table)
  17. // Can solve Range Queries for:
  18. // Max, Min, Sum, GCD, LCM.
  19. // And anything else where we can combine segments in O(1).
  20. // The pair operations here take use of the fact that pairs can be compared element wise.
  21. // For Sum, GCD, LCM, remove the index entirely (Because it doesn't make sense)
  22. // O(n*log(n)) build, O(1) query
  23. template <typename T> struct SparseTable {
  24. int n; vector<vector<pair<T, int> > > sptable; vi lg;
  25. SparseTable(const vector<T> &A) : n(A.size()), lg(n+1, 0) {
  26. for (int i=2; i <= n; i++) lg[i] = lg[i/2] + 1;
  27. sptable.assign(lg[n]+1, vector<pair<T, int> >(n));
  28. for (int i=0; i<n; i++) sptable[0][i] = {A[i], i}; // query [x, x] = x.
  29. for (int i=1; i<=lg[n]; i++) for (int j=0; j+(1<<i)-1<n; j++)
  30. sptable[i][j] = min(sptable[i-1][j], sptable[i-1][j+(1<<(i-1))]); // Combine segments (Change here.)
  31. }
  32. pair<T, int> query(int L, int R) {
  33. int k = lg[R-L+1];
  34. return min(sptable[k][L], sptable[k][R-(1<<k)+1]); // Combine segments (Change here.)
  35. }
  36. };
  37.  
  38. // Dynamic RQ, with lazy propogation (Ranged updates.)
  39. // Updates and querys are INCLUSIVE ON BOTH SIDES [L, R].
  40. template<typename T, typename U> struct SegmentTree {
  41. int S, H;
  42.  
  43. T z;
  44. vector<T> v; // Actual values (May not be up to date)
  45.  
  46. U noop; // No Operation constant
  47. vector<bool> d; // Dirty array (What needs updating)
  48. vector<U> p; // Lazy propogated updates.
  49.  
  50. SegmentTree<T, U>(int _S, T _z = T(), U _noop = U()) {
  51. z = _z, noop = _noop;
  52. for (S = 1, H = 1; S < _S; ) S *= 2, H++;
  53. v.resize(2*S, z);
  54. d.resize(2*S, false);
  55. p.resize(2*S, noop);
  56. }
  57.  
  58. void set_leaves(vector<T> &l) {
  59. copy(l.begin(), l.end(), v.begin() + S);
  60. for (int i = S - 1; i > 0; i--)
  61. v[i] = v[2 * i] + v[2 * i + 1];
  62. }
  63.  
  64. void apply(int i, U &up) {
  65. v[i] = up(v[i]);
  66. if(i < S) {
  67. p[i] = p[i] + up;
  68. d[i] = true;
  69. }
  70. }
  71.  
  72. void rebuild(int i) {
  73. for (int l = i/2; l; l /= 2) {
  74. T c = v[2*l] + v[2*l+1];
  75. v[l] = p[l](c);
  76. }
  77. }
  78.  
  79. void prop(int i) {
  80. for (int h = H; h > 0; h--) {
  81. int l = i >> h;
  82.  
  83. if (d[l]) {
  84. apply(2*l, p[l]);
  85. apply(2*l+1, p[l]);
  86.  
  87. p[l] = noop;
  88. d[l] = false;
  89. }
  90. }
  91. }
  92.  
  93. void upd(int i, int j, U update) {
  94. i += S, j += S;
  95. prop(i), prop(j);
  96.  
  97. for (int l = i, r = j; l <= r; l /= 2, r /= 2) {
  98. if((l&1) == 1) apply(l++, update);
  99. if((r&1) == 0) apply(r--, update);
  100. }
  101.  
  102. rebuild(i), rebuild(j);
  103. }
  104.  
  105. T query(int i, int j){
  106. i += S, j += S;
  107. prop(i), prop(j);
  108.  
  109. T res_left = z, res_right = z;
  110. for(; i <= j; i /= 2, j /= 2){
  111. if((i&1) == 1) res_left = res_left + v[i++];
  112. if((j&1) == 0) res_right = v[j--] + res_right;
  113. }
  114. return res_left + res_right;
  115. }
  116. };
  117.  
  118. /* Example structures for minimum with increment and global update. */
  119. struct minNode {
  120. ll minim;
  121.  
  122. // How are minimums combined?
  123. minNode operator+(const minNode &n) {
  124. return { min(n.minim, minim) };
  125. }
  126. };
  127.  
  128. struct minUpdate {
  129. bool type; // true => increment; false => set.
  130. ll value;
  131.  
  132. // How do we apply an operation?
  133. minNode operator()(const minNode &n) {
  134. return { type ? n.minim + value : value };
  135. }
  136.  
  137. minUpdate operator+(const minUpdate &u) {
  138. if (type) {
  139. // Increment
  140. return { u.type, u.value + value};
  141. }
  142. // Set
  143. return { type, value };
  144. }
  145. };
  146.  
  147. const minNode minZero { INT_MAX };
  148. const minUpdate minNoUp { true, 0 }; // Increment by 0 by default.
  149.  
  150. /* Example structures for sum with increment and global update. */
  151. struct sumNode {
  152. ll value;
  153. ll width; // How many leaves does this node span?
  154.  
  155. // How are sums combined?
  156. sumNode operator+(const sumNode &n) {
  157. return { value + n.value, width + n.width };
  158. }
  159. };
  160.  
  161. struct sumUpdate {
  162. bool type; // true => increment; false => set.
  163. ll value;
  164.  
  165. // How do we apply an operation?
  166. sumNode operator()(const sumNode &n) {
  167. return { type ? n.value + value * n.width : value * n.width, n.width };
  168. }
  169.  
  170. sumUpdate operator+(const sumUpdate &u) {
  171. if (type) {
  172. // Increment
  173. return { u.type, u.value + value};
  174. }
  175. // Set
  176. return { type, value };
  177. }
  178. };
  179.  
  180. const sumNode sumZero { 0, 1 }; // Width 1.
  181. const sumUpdate sumNoUp { true, 0 }; // Increment by 0 by default.
  182.  
  183. /* Example structures for gcd with multiply and global update. */
  184. struct gcdNode {
  185. ll value;
  186.  
  187. // How are gcds combined?
  188. gcdNode operator+(const gcdNode &n) {
  189. if (n.value == -1) return { value };
  190. if (value == -1) return { n.value };
  191. return { gcd(n.value, value) };
  192. }
  193. };
  194.  
  195. struct gcdUpdate {
  196. bool type; // true => multiply; false => set.
  197. ll value;
  198.  
  199. // How do we apply an operation?
  200. gcdNode operator()(const gcdNode &n) {
  201. return { type ? n.value * value : value };
  202. }
  203.  
  204. gcdUpdate operator+(const gcdUpdate &u) {
  205. if (type) {
  206. // Multiply
  207. return { u.type, u.value * value};
  208. }
  209. // Set the gcd
  210. return { type, value };
  211. }
  212. };
  213.  
  214. const gcdNode gcdZero { -1 }; // Width 1.
  215. const gcdUpdate gcdNoUp { true, 1 }; // Multiply by 1 by default.
  216.  
  217. int main() {
  218.  
  219. vector<int> list;
  220. list.push_back(3);
  221. list.push_back(5);
  222. list.push_back(2);
  223. list.push_back(4);
  224. list.push_back(1);
  225. list.push_back(5);
  226. list.push_back(3);
  227. list.push_back(2);
  228.  
  229. SparseTable<int> s(list);
  230. SegmentTree<minNode, minUpdate> st(list.size(), minZero, minNoUp);
  231. vector<minNode> nodeList;
  232. for (int i=0; i<list.size(); i++) {
  233. nodeList.push_back({ list[i] });
  234. }
  235. st.set_leaves(nodeList);
  236.  
  237. cout << "Static vs Dynamic Min" << endl;
  238. // 0, 1, 2, 3, 4, 5, 6, 7
  239. // 3, 5, 2, 4, 1, 5, 3, 2
  240. cout << s.query(3, 7).first << " " << s.query(3, 7).second << endl;
  241. cout << st.query(3, 7).minim << endl;
  242. // 1 4, 1
  243. cout << s.query(0, 2).first << " " << s.query(0, 2).second << endl;
  244. cout << st.query(0, 2).minim << endl;
  245. // 2 2, 2
  246. st.upd(2, 4, { true, 1 }); // Increment [2, 4] by 2.
  247. cout << s.query(2, 6).first << " " << s.query(2, 6).second << endl;
  248. cout << st.query(2, 6).minim << endl;
  249. // 1 4, 2
  250. st.upd(4, 4, { false, 10 }); // Set [4, 4] to 10
  251. cout << st.query(4, 4).minim << endl;
  252. // 10
  253.  
  254. cout << "Sum Updates" << endl;
  255. SegmentTree<sumNode, sumUpdate> st2(list.size(), sumZero, sumNoUp);
  256. vector<sumNode> sumList;
  257. for (int i=0; i<list.size(); i++) {
  258. sumList.push_back({ list[i], 1 });
  259. }
  260. st2.set_leaves(sumList);
  261.  
  262. // 0, 1, 2, 3, 4, 5, 6, 7
  263. // 3, 5, 2, 4, 1, 5, 3, 2
  264. for (int i=0; i<8; i++) {
  265. cout << st2.query(i, i).value << " ";
  266. }
  267. cout << endl;
  268. cout << st2.query(0, 7).value << " " << st2.query(2, 5).value << endl;
  269. // 25 12
  270. st2.upd(1, 5, { false, 1 }); // Set all of [1, 5] to 1.
  271. cout << st2.query(1, 5).value << " " << st2.query(0, 7).value << endl;
  272. // 5 13
  273. st2.upd(4, 7, { true, 2 }); // Increment [4, 7] by 2.
  274. cout << st2.query(2, 5).value << " " << st2.query(0, 7).value << endl;
  275. // 8 21
  276.  
  277. cout << "GCD Range Updates" << endl;
  278. SegmentTree<gcdNode, gcdUpdate> st3(list.size(), gcdZero, gcdNoUp);
  279. vector<gcdNode> gcdList;
  280. for (int i=0; i<list.size(); i++) {
  281. gcdList.push_back({ list[i] });
  282. }
  283. st3.set_leaves(gcdList);
  284.  
  285. // 0, 1, 2, 3, 4, 5, 6, 7
  286. // 3, 5, 2, 4, 1, 5, 3, 2
  287. cout << st3.query(2, 2).value << " " << st3.query(4, 4).value << endl;
  288. // 2 1
  289. st3.upd(4, 6, { true, 2 }); // Multiply [4, 6] by 2.
  290. st3.upd(2, 3, { true, 10 }); // Multiply [2, 3] by 10.
  291. cout << st3.query(3, 7).value << " " << st3.query(2, 3).value << endl;
  292. // 2 20
  293. st3.upd(0, 0, { false, 6 });
  294. st3.upd(7, 7, { false, 15 });
  295. st3.upd(1, 6, { true, 4 });
  296. st3.upd(1, 6, { true, 3 });
  297. cout << st3.query(0, 7).value << " " << st3.query(0, 6).value << endl;
  298. // 3 6
  299. return 0;
  300. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement