Advertisement
i_love_rao_khushboo

Descent in Segment Tree.cpp

Oct 14th, 2021
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.84 KB | None | 0 0
  1. /*
  2. KEYNOTES:
  3. ------------------------------------------------------------------------------------------
  4. merge(X,identity_element) = X
  5. ------------------------------------------------------------------------------------------
  6. // (i.e no transformation at all or if we combine any new update with the identity update
  7. // it should give the newer update)
  8. identity_transformation.combine(X) = X
  9. ------------------------------------------------------------------------------------------
  10. ALWAYS: older_update.combine(newer_update)
  11. ------------------------------------------------------------------------------------------
  12. */
  13.  
  14. // this structure depends on the nature of query
  15. struct node {
  16.     // 1. change(s) required
  17.     // use more variables if you want more information
  18.     // these default values should be identity_element
  19.    
  20.        
  21.     node() {}
  22.     node(int ) {
  23.         // 2. change(s) required
  24.        
  25.     }
  26.    
  27.     // associative merging function, store the thing you wanna query
  28.     void merge(node &l, node &r){
  29.         // 3. change(s) required
  30.        
  31.     }
  32.    
  33.     bool check(int x) {
  34.         // 4. change(s) required
  35.        
  36.     }
  37. };
  38.  
  39. // this structure depends on the nature of update
  40. struct update {
  41.     // 5. change(s) required
  42.     // use more variables if you want more information
  43.     // these default values should be identity_transformation or identity_update
  44.    
  45.    
  46.     update() {}
  47.     update(int ) {
  48.         // 6. change(s) required
  49.        
  50.     }
  51.    
  52.     // combine the current update with the other update (see keynotes)
  53.     // basically combine older lazy value(s) (if exist) with newer one(s).
  54.     // for this function, you can be sure that the "other" is newer than current
  55.     void combine(update &other, int &tl, int &tr) {
  56.         // 7. change(s) required
  57.        
  58.     }
  59.    
  60.     // store the correct information in the node x
  61.     void apply(node &x, int &tl, int &tr) {
  62.         // 8. change(s) required
  63.        
  64.     }
  65. };
  66.  
  67. template<typename node, typename update>
  68. struct segtree {
  69.     int len;
  70.     bool built;
  71.     node zero;
  72.     update noop;
  73.     vector<node> t;
  74.     vector<update> upds;
  75.     vector<int> tl, tr;
  76.     vector<bool> lazy;
  77.    
  78.     segtree(int l) {
  79.         len = l;
  80.         built = false;
  81.         zero = node();
  82.         noop = update();
  83.         t.clear(); t.resize(4 * len, zero);
  84.         upds.clear(); upds.resize(4 * len, noop);
  85.         tl.clear(); tl.resize(4 * len);
  86.         tr.clear(); tr.resize(4 * len);
  87.         lazy.clear(); lazy.resize(4 * len, false);
  88.     }
  89.    
  90.     inline void pushdown(int v) {
  91.         if(!lazy[v]) return;
  92.         apply(v * 2, upds[v]);
  93.         apply(v * 2 + 1, upds[v]);
  94.         lazy[v] = 0;
  95.         upds[v] = noop;
  96.     }
  97.    
  98.     inline void apply(int v, update &val) {
  99.         if(tl[v] != tr[v]) {
  100.             lazy[v] = 1;
  101.             upds[v].combine(val, tl[v], tr[v]);
  102.         }
  103.        
  104.         val.apply(t[v], tl[v], tr[v]);
  105.     }
  106.    
  107.     template<typename T>
  108.     void build(T &a, int v, int l, int r) {
  109.         tl[v] = l;
  110.         tr[v] = r;
  111.        
  112.         if(l == r) {
  113.             t[v] = a[l];
  114.             return;
  115.         }
  116.        
  117.         int tm = (l + r) / 2;
  118.         build(a, v * 2, l, tm);
  119.         build(a, v * 2 + 1, tm + 1, r);
  120.         t[v].merge(t[v * 2], t[v * 2 + 1]);
  121.     }
  122.    
  123.     node query(int v, int l, int r) {
  124.         if(l > tr[v] || r < tl[v]) return zero;
  125.         if(l <= tl[v] && tr[v] <= r) return t[v];
  126.        
  127.         pushdown(v);
  128.         node a, b, ans;
  129.         a = query(v * 2, l, r);
  130.         b = query(v * 2 + 1, l, r);
  131.         ans.merge(a, b);
  132.         return ans;
  133.     }
  134.    
  135.     void rupd(int v, int l, int r, update &val) {
  136.         if(l > tr[v] || r < tl[v]) return;
  137.         if(l <= tl[v] && tr[v] <= r) {
  138.             apply(v,val);
  139.             return;
  140.         }
  141.        
  142.         pushdown(v);
  143.         rupd(v * 2, l, r, val);
  144.         rupd(v * 2 + 1, l, r, val);
  145.         t[v].merge(t[v * 2], t[v * 2 + 1]);
  146.     }
  147.    
  148.     template<typename T>
  149.     int descent_right(int l, T x, int v, node &prev) {
  150.         // node is completely out of range
  151.         if(l > tr[v]) return len;
  152.        
  153.         // node is completely in range
  154.         if(l <= tl[v]) {
  155.             node cur;
  156.             cur.merge(prev, t[v]);
  157.            
  158.             // go further right than this node
  159.             if(!cur.check(x)) {
  160.                 // merging this node's contribution
  161.                 swap(prev,cur);
  162.                 return len;
  163.             }
  164.            
  165.             if(tl[v] == tr[v]) {
  166.                 return tr[v];
  167.             }
  168.         }
  169.        
  170.         pushdown(v);
  171.         int ans = descent_right(l, x, v * 2, prev); // trying to find in left child
  172.         if(ans != len) return ans; // found in left child
  173.         return descent_right(l, x, v * 2 + 1, prev); // finding in right child
  174.     }
  175.    
  176.     template<typename T>
  177.     int descent_left(int r, T x, int v, node &prev) {
  178.         // node is completely out of range
  179.         if(r < tl[v]) return -1;
  180.        
  181.         // node is completely in range
  182.         if(r >= tr[v]) {
  183.             node cur;
  184.             cur.merge(t[v], prev);
  185.            
  186.             // go further left than this node
  187.             if(!cur.check(x)){
  188.                 // merging this node's contribution
  189.                 swap(cur,prev);
  190.                 return -1;
  191.             }
  192.            
  193.             if(tl[v] == tr[v]) {
  194.                 return tl[v];
  195.             }
  196.         }
  197.        
  198.         pushdown(v);
  199.         int ans = descent_left(r, x, v * 2 + 1, prev); // trying to find in right child
  200.         if(ans != -1) return ans; // found in right child
  201.         return descent_left(r, x, v * 2, prev); // finding in left child
  202.     }
  203.    
  204.     public:
  205.     template<typename T>
  206.     void build(T &a) {
  207.         build(a, 1, 0, len - 1);
  208.         built = true;
  209.     }
  210.    
  211.     template<typename T>
  212.     // minimum r such that [l...r].check(x) == true, returns segtree.len if not found
  213.     int descent_right(int l, T x) {
  214.         node prev = zero;
  215.         return descent_right(l, x, 1, prev);
  216.     }
  217.    
  218.     // maximum l such that [l...r].check(x) == true, returns -1 if not found
  219.     template<typename T>
  220.     int descent_left(int r, T x) {
  221.         node prev = zero;
  222.         return descent_left(r, x, 1, prev);
  223.     }
  224.    
  225.     node query(int l, int r) {
  226.         if(!built) build(t);
  227.         return query(1, l, r);
  228.     }
  229.    
  230.     void rupd(int l, int r, update val) {
  231.         if(!built) build(t);
  232.         rupd(1, l, r, val);
  233.     }
  234. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement