Submission #780902

# Submission time Handle Problem Language Result Execution time Memory
780902 2023-07-12T14:29:26 Z LCPlayer Monkey and Apple-trees (IZhO12_apple) C++14
0 / 100
516 ms 262144 KB
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) 88
#define dout if (0) cout
#endif
template<typename typC> istream &operator>>(istream &cin,vector<typC> &a) { for (int i=0;i<a.size();i++) cin>>a[i]; return cin; }
template<typename typC> ostream &operator<<(ostream &cout,const vector<typC> &a) { int n=a.size(); if (!n) return cout; cout<<a[0]; for (int i=1; i<n; i++) cout<<' '<<a[i]; return cout; }
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
#define RE(i, n) for (int i = 0; i < n; i++)
#define RE2(i, start, n) for (int i = start; i < n; i++)
 
// #define MULTI_CASES
// #define LOCAL_MULTI_CASES
 
template <class T>
struct TreeNode {
  T value = 0;
  bool lazy = false;
  T lazyValue = 0;
  TreeNode *leftChild = NULL, *rightChild = NULL;
};
template <class T>
class PersistentSegmentTree {
public:
  PersistentSegmentTree(vector<T>& data) : n(data.size()) { root = new TreeNode<T>(); build(root, data, 0, n - 1); }
  // n is the max value bound (exclusive), allowed range is [0, n - 1]. // not tested yet
  PersistentSegmentTree(int n) : n(n) { root = new TreeNode<T>(); }
  // Could be copied to keep history at this moment.
  PersistentSegmentTree(const PersistentSegmentTree& pst) : n(pst.n), root(pst.root) {}
  // Range update [i, j] to val.
  void update(int i, int j, T val) { root = update(root, 0, n - 1, i, j, val); }
  // Range query [i, j].
  T query(int i, int j) { return query(root, 0, n - 1, i, j); }
  void clear() { clear(root); }
private:
  int n;
  TreeNode<T>* root;
  void build(TreeNode<T>* curr, vector<T>& data, int L, int R) {
    if (L == R) { curr->value = data[L]; return; }
    expand(curr, L, R);
    int m = (L + R) / 2;
    build(curr->leftChild, data, L, m); build(curr->rightChild, data, m + 1, R);
    curr->value = calculate(curr->leftChild->value, curr->rightChild->value);
  }
  void expand(TreeNode<T>* curr, int L, int R) {
    if (!curr->leftChild) { curr->leftChild = new TreeNode<T>(); }
    if (!curr->rightChild) { curr->rightChild = new TreeNode<T>(); }
  }
  T calculate(T v1, T v2) {
    return v1 + v2; // case by case 1/4.
  }
  // propagate lazy value one level down.
  void propagate(TreeNode<T>* curr, int L, int R) {
    if (!curr->lazy) return;
    if (L == R) {
      // case by case 2/4.
      // data[L] += curr->lazyValue; // leaf node; time to update.
    } else {
      TreeNode<T> *lc = curr->leftChild, *rc = curr->rightChild; int m = (L + R) / 2;
      lc->lazy = rc->lazy = true;
      // case by case 3/4.
      lc->lazyValue = curr->lazyValue;
      rc->lazyValue = curr->lazyValue;
      lc->value = (m - L + 1) * curr->lazyValue;
      rc->value = (R - (m + 1) + 1) * curr->lazyValue;
    }
    curr->lazy = false; curr->lazyValue = 0;
  }

  TreeNode<T>* update(TreeNode<T>* curr, int L, int R, int i, int j, T val) {
    assert(L <= i && i <= j && j <= R);
    expand(curr, L, R);
    propagate(curr, L, R);
    TreeNode<T>* newCurr = new TreeNode<T>();
    // copy first
    newCurr->leftChild = curr->leftChild; newCurr->rightChild = curr->rightChild;
    if (i == L && j == R) {
      // case by case 4/4.
      newCurr->lazyValue = val;
      newCurr->value = (R - L + 1) * val;
      newCurr->lazy = true;
      return newCurr;
    }
    int m = (L + R) / 2; 
    TreeNode<T> *lc = newCurr->leftChild, *rc = newCurr->rightChild;
    if (i <= m) { lc = newCurr->leftChild = update(lc, L, m, i, min(m, j), val); }
    if (j >= m + 1) { rc = newCurr->rightChild = update(rc, m + 1, R, max(i, m + 1), j, val); }
    T lValue = lc->value; T rValue = rc->value;
    newCurr->value = calculate(lValue, rValue);
    return newCurr;
  }

  T query(TreeNode<T>* curr, int L, int R, int i, int j) {
    assert(L <= i && i <= j && j <= R);
    T ans;
    if (i == L && j == R) { 
      ans = curr->value;
    } else {
      expand(curr, L, R);
      propagate(curr, L, R); int m = (L + R) / 2;
      TreeNode<T> *lc = curr->leftChild, *rc = curr->rightChild;
      if (j <= m) { ans = query(lc, L, m, i, j);
      } else if (i >= m + 1) { ans = query(rc, m + 1, R, i, j);
      } else {
        T lValue = query(lc, L, m, i, m);
        T rValue = query(rc, m + 1, R, m + 1, j);
        ans = calculate(lValue, rValue);
      }
    }
    return ans;
  }
};
 
void solve() {
  int n;
  cin >> n;
  debug(n);
  int preans = 0;
  PersistentSegmentTree<int> st(1000000000);
  RE(i, n) {
    int type, x, y;
    cin >> type >> x >> y;    
    x += preans; y += preans;
    x--; y--;
    
    if (type == 1) {
      // query
      preans = st.query(x, y);
      cout << preans << "\n";
    } else {
      assert(type == 2);
      // update
      st.update(x, y, 1);
    }
  }
}
 
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  
  int cases = 1;
  #if defined MULTI_CASES || (defined LOCAL && defined LOCAL_MULTI_CASES)
  cin >> cases;
  #endif
  for (int i = 0; i < cases; i++) {
    dout << "cases: " << i + 1 << endl;
    solve();
    dout << endl;
  }
  
  return 0;
}

Compilation message

apple.cpp: In function 'void solve()':
apple.cpp:6:20: warning: statement has no effect [-Wunused-value]
    6 | #define debug(...) 88
      |                    ^~
apple.cpp:122:3: note: in expansion of macro 'debug'
  122 |   debug(n);
      |   ^~~~~
# Verdict Execution time Memory Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 1 ms 212 KB Output is correct
3 Correct 1 ms 324 KB Output is correct
4 Correct 29 ms 18916 KB Output is correct
5 Correct 27 ms 23016 KB Output is correct
6 Correct 30 ms 23632 KB Output is correct
7 Correct 30 ms 23080 KB Output is correct
8 Correct 257 ms 135012 KB Output is correct
9 Correct 516 ms 259240 KB Output is correct
10 Runtime error 491 ms 262144 KB Execution killed with signal 9
11 Halted 0 ms 0 KB -