제출 #1214638

#제출 시각아이디문제언어결과실행 시간메모리
1214638wckiipiMonkey and Apple-trees (IZhO12_apple)C++20
100 / 100
314 ms213480 KiB
// #include <bits/stdc++.h>
#include <algorithm>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#define MAX_INT 2147483647
// #define INT_MIN -2147483648
bool CHECK_FOR_TESTCASE = false;
bool CHECK_NOW = false;
bool FIRST_TESTCASE = true;

using namespace std;
// For tree, uncomment below
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
template <typename T>
using Tree =
    __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag,
                     __gnu_pbds::tree_order_statistics_node_update>;

void __print(int x) { cerr << x; }
void __print(long x) { cerr << x; }
void __print(long long x) { cerr << x; }
void __print(unsigned x) { cerr << x; }
void __print(unsigned long x) { cerr << x; }
void __print(unsigned long long x) { cerr << x; }
void __print(float x) { cerr << x; }
void __print(double x) { cerr << x; }
void __print(long double x) { cerr << x; }
void __print(char x) { cerr << '\'' << x << '\''; }
void __print(const char *x) { cerr << '\"' << x << '\"'; }
void __print(const string &x) { cerr << '\"' << x << '\"'; }
void __print(bool x) { cerr << (x ? "true" : "false"); }

template <typename T, typename V> void __print(const pair<T, V> &x) {
  cerr << '{';
  __print(x.first);
  cerr << ',';
  __print(x.second);
  cerr << '}';
}
template <typename T> void __print(const T &x) {
  int f = 0;
  cerr << '{';
  for (auto &i : x)
    cerr << (f++ ? "," : ""), __print(i);
  cerr << "}";
}

template <typename T> void __print(stack<T> s) {
  vector<T> elements;
  while (!s.empty()) {
    elements.push_back(s.top());
    s.pop();
  }
  reverse(elements.begin(), elements.end());
  __print(elements);
}

template <typename T> void __print(queue<T> q) {
  vector<T> elements;
  while (!q.empty()) {
    elements.push_back(q.front());
    q.pop();
  }
  __print(elements);
}
void _print() { cerr << "]\n"; }
template <typename T, typename... V> void _print(T t, V... v) {
  __print(t);
  if (sizeof...(v))
    cerr << ", ";
  _print(v...);
}
#ifdef LOCAL_PROJECT
#define debug(x...)                                                            \
  cerr << "[" << #x << "] = [";                                                \
  _print(x)
#else
#define debug(x...)
#endif

typedef long long ll;
typedef unsigned long long ull;

ll exp(ll a, ll b, ll mod) {
  ll res = 1;
  while (b > 0) {
    if (b & 1) {
      res = res * a % mod;
    }
    a = a * a % mod;
    b >>= 1;
  }
  return res;
}

int N = 5e5 + 5;
vector<ll> fact(N + 1, 1);
vector<ll> inv(N + 1, 1);
ll mod = 998244353;
#define MOD 1000000007

ll ncr(int n, int r) {
  if (r > n) {
    return 0;
  }
  return fact[n] * inv[r] % mod * inv[n - r] % mod;
}

int add(int a, int b) {
  if ((a += b) >= mod)
    a -= mod;

  return a;
}

class DisjointSets {

private:
  vector<int> parents;
  vector<int> sizes;

public:
  DisjointSets(int size) : parents(size), sizes(size, 1) {

    for (int i = 0; i < size; i++) {
      parents[i] = i;
    }
  }

  /** @return the "representative" node in x's component */

  int find(int x) {
    return parents[x] == x ? x : (parents[x] = find(parents[x]));
  }

  /** @return whether the merge changed connectivity */

  bool unite(int x, int y) {
    int x_root = find(x);

    int y_root = find(y);

    if (x_root == y_root) {
      return false;
    }

    if (sizes[x_root] < sizes[y_root]) {
      swap(x_root, y_root);
    }

    sizes[x_root] += sizes[y_root];

    parents[y_root] = x_root;

    return true;
  }

  /** @return whether x and y are in the same connected component */

  bool connected(int x, int y) { return find(x) == find(y); }

  int getSize(int x) { return sizes[find(x)]; }

  int getNumComponents() {
    int count = 0;
    for (int i = 0; i < (int)parents.size(); i++) {
      if (parents[i] == i) {
        count++;
      }
    }
    return count;
  }
};
//
// int mul(int a, int b) { return int(1LL * a * b % MOD); }

// int n = 700, m = 700;

// const ll MOD = 998244353;

struct custom_hash {
  static uint64_t splitmix64(uint64_t x) {
    // SplitMix64 hashing algorithm
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
  }

  size_t operator()(uint64_t x) const {
    static const uint64_t FIXED_RANDOM =
        chrono::steady_clock::now().time_since_epoch().count();
    return splitmix64(x + FIXED_RANDOM);
  }
};

struct STree {
private:
  int n;
  vector<int> a;
  void update(int node, int nodeMin, int nodeMax, int queryLeft, int queryRight,
              int x) {
    if (nodeMin >= queryLeft && nodeMax <= queryRight) {
      a[node] = x;
      return;
    }
    if (nodeMin > queryRight || nodeMax < queryLeft) {
      return;
    }
    int mid = nodeMin + (nodeMax - nodeMin) / 2;
    update(node * 2, nodeMin, mid, queryLeft, queryRight, x);
    update(node * 2 + 1, mid + 1, nodeMax, queryLeft, queryRight, x);

    a[node] = a[node * 2] + a[node * 2 + 1];
  }

  int query(int node, int nodeMin, int nodeMax, int queryLeft, int queryRight) {
    if (nodeMin >= queryLeft && nodeMax <= queryRight) {
      return a[node];
    }
    if (nodeMin > queryRight || nodeMax < queryLeft) {
      return 0;
    }

    int mid = nodeMin + (nodeMax - nodeMin) / 2;
    int left = query(node * 2, nodeMin, mid, queryLeft, queryRight);
    int right = query(node * 2 + 1, mid + 1, nodeMax, queryLeft, queryRight);

    return left + right;
  };

public:
  STree(int _n) : n(_n) { a.resize(4 * _n, 0); };

  void up(int pos, int x) { update(1, 0, n - 1, pos, pos, x); }
  void add(int pos, int x) {
    int val = query(1, 0, n - 1, pos, pos);
    update(1, 0, n - 1, pos, pos, val + x);
  }

  int q(int queryLeft, int queryRight) {
    return query(1, 0, n - 1, queryLeft, queryRight);
  }
};

struct SegTree {
private:
  vector<ll> a;
  vector<ll> lazy;
  ll DEFAULT = 0;
  int n;

  void push(int node, int nodeMin, int nodeMax) {
    if (lazy[node] == 0) {
      return;
    }
    if (nodeMin != nodeMax) {
      int nodeMid = (nodeMin + nodeMax) / 2;

      ll left_size = nodeMid - nodeMin + 1;
      ll right_size = nodeMax - nodeMid;
      if (lazy[node] >= 0) {
        a[node * 2] += (left_size * lazy[node]);
        a[node * 2 + 1] += (right_size * lazy[node]);
        lazy[node * 2] += lazy[node];
        lazy[node * 2 + 1] += lazy[node];
      } else {
        a[node * 2] = (left_size * -lazy[node]);
        a[node * 2 + 1] = (right_size * -lazy[node]);
        lazy[node * 2] = lazy[node];
        lazy[node * 2 + 1] = lazy[node];
      }
    }
    lazy[node] = 0;
  }

  void update(int node, int nodeMinimum, int nodeMaximum, int queryLow,
              int queryHigh, ll value) {
    int nodeMiddle = (nodeMinimum + nodeMaximum) / 2;

    ll left_size = nodeMiddle - nodeMinimum + 1;
    ll right_size = nodeMaximum - nodeMiddle;
    if (nodeMinimum >= queryLow && nodeMaximum <= queryHigh) {
      a[node] += (value * (ll)(nodeMaximum - nodeMinimum + 1));
      lazy[node] += value;
      return;
    }
    if (nodeMaximum < queryLow || nodeMinimum > queryHigh) {
      return;
    }

    push(node, nodeMinimum, nodeMaximum);
    update(node * 2, nodeMinimum, nodeMiddle, queryLow, queryHigh, value);
    update(node * 2 + 1, nodeMiddle + 1, nodeMaximum, queryLow, queryHigh,
           value);
    // a[node] = min(a[node * 2], a[node * 2 + 1]);
    a[node] = a[node * 2] + a[node * 2 + 1];
  }
  void updateValue(int node, int nodeMinimum, int nodeMaximum, int queryLow,
                   int queryHigh, ll value) {
    int nodeMiddle = (nodeMinimum + nodeMaximum) / 2;

    ll left_size = nodeMiddle - nodeMinimum + 1;
    ll right_size = nodeMaximum - nodeMiddle;
    if (nodeMinimum >= queryLow && nodeMaximum <= queryHigh) {
      // a[node] = (value * (ll)(nodeMaximum - nodeMinimum + 1));
      a[node] = (value * (ll)(nodeMaximum - nodeMinimum + 1));
      lazy[node] = -value;
      // lazy[node] += value;
      return;
    }
    if (nodeMaximum < queryLow || nodeMinimum > queryHigh) {
      return;
    }

    push(node, nodeMinimum, nodeMaximum);
    update(node * 2, nodeMinimum, nodeMiddle, queryLow, queryHigh, value);
    update(node * 2 + 1, nodeMiddle + 1, nodeMaximum, queryLow, queryHigh,
           value);
    // a[node] = min(a[node * 2], a[node * 2 + 1]);
    a[node] = a[node * 2] + a[node * 2 + 1];
  }

  ll query(int node, int nodeMinimum, int nodeMaximum, int queryLow,
           int queryHigh) {
    if (nodeMinimum >= queryLow && nodeMaximum <= queryHigh) {
      return a[node];
    }
    if (nodeMaximum < queryLow || nodeMinimum > queryHigh) {
      return 0;
    }

    int nodeMiddle = (nodeMinimum + nodeMaximum) / 2;
    push(node, nodeMinimum, nodeMaximum);
    ll solution =
        query(node * 2, nodeMinimum, nodeMiddle, queryLow, queryHigh) +
        query(node * 2 + 1, nodeMiddle + 1, nodeMaximum, queryLow, queryHigh);

    return solution;
  }

public:
  SegTree(int _n) : n(_n) {
    a.resize(4 * _n, DEFAULT);
    lazy.resize(4 * _n, 0);
  }
  void updateVal(int l, int r, ll x) { updateValue(1, 0, n - 1, l, r, x); }
  void updateRange(int l, int r, ll x) { update(1, 0, n - 1, l, r, x); }
  ll que(int l, int r) { return query(1, 0, n - 1, l, r); }
  // int find(int l, int r, int k) {
  //   if (l == r) {
  //     if (que(l, r) < k) {
  //       return INT_MIN;
  //     } else {
  //       return l;
  //     }
  //   }
  //   int mid = l + (r - l) / 2;
  //   int maxL = que(l, mid);
  //   if (maxL >= k) {
  //     return find(l, mid, k);
  //   } else {
  //     return find(mid + 1, r, k);
  //   }
  // }
};

struct sparseSegment {

public:
  struct Node {
    Node *l, *r;
    ll a;
    Node(ll _a) : l(nullptr), r(nullptr), a(_a) {}
  };
  sparseSegment(int _n) : n(_n) { root = new Node(DEFAULT); }

  int n;
  ll DEFAULT = 0;
  Node *root;

  ll query(Node *node, int nodeMin, int nodeMax, int queryLow, int queryHigh) {
    int nodeMid = (nodeMin + nodeMax) / 2;
    if (node == nullptr) {
      return DEFAULT;
    }
    if (nodeMin >= queryLow && nodeMax <= queryHigh) {
      return node->a;
    }
    if (nodeMax < queryLow || nodeMin > queryHigh) {
      return DEFAULT;
    }

    ll left = query(node->l, nodeMin, nodeMid, queryLow, queryHigh);
    ll right = query(node->r, nodeMid + 1, nodeMax, queryLow, queryHigh);
    return left + right;
  }

  void update(Node *&node, int nodeMin, int nodeMax, int queryLow,
              int queryHigh, ll x) {
    if (node == nullptr) {
      node = new Node(0);
    }
    if (nodeMin >= queryLow && nodeMax <= queryHigh) {
      node->a = x;
      return;
    }
    if (nodeMax < queryLow || nodeMin > queryHigh) {
      return;
    }
    int nodeMid = (nodeMin + nodeMax) / 2;
    update(node->l, nodeMin, nodeMid, queryLow, queryHigh, x);
    update(node->r, nodeMid + 1, nodeMax, queryLow, queryHigh, x);
    ll left = node->l ? node->l->a : DEFAULT;
    ll right = node->r ? node->r->a : DEFAULT;
    node->a = left + right;
  }
};

struct LazySparseSegmentTree {
  int n;
  struct Node {
    ll a = 0;
    Node *l, *r;
    ll lazy = -1;
    Node(ll _a) : a(_a), l(nullptr), r(nullptr) {}
  };
  Node *root = nullptr;

  LazySparseSegmentTree(int _n) : n(_n) { root = new Node(0); }

  void push(Node *node, int nodeLow, int nodeHigh) {
    if (node == nullptr || node->lazy == -1) {
      return;
    }
    if (node->l == nullptr) {
      node->l = new Node(0);
    }
    if (node->r == nullptr) {
      node->r = new Node(0);
    }
    int nodeMid = nodeLow + (nodeHigh - nodeLow) / 2;
    int left = nodeMid - nodeLow + 1;
    int right = nodeHigh - nodeMid;

    node->l->a = left * node->lazy;
    node->l->lazy = node->lazy;
    node->r->a = right * node->lazy;
    node->r->lazy = node->lazy;
    node->lazy = -1;
  }

  void update(Node *&node, int nodeLow, int nodeHigh, int queryLow,
              int queryHigh, ll x) {
    if (node == nullptr) {
      node = new Node(0);
    }
    int nodeMid = nodeLow + (nodeHigh - nodeLow) / 2;
    ll size = nodeHigh - nodeLow + 1;

    if (nodeLow >= queryLow && nodeHigh <= queryHigh) {
      node->a = x * size;
      node->lazy = x;
      return;
    }
    if (nodeHigh < queryLow || nodeLow > queryHigh) {
      return;
    }
    push(node, nodeLow, nodeHigh);
    update(node->l, nodeLow, nodeMid, queryLow, queryHigh, x);
    update(node->r, nodeMid + 1, nodeHigh, queryLow, queryHigh, x);
    node->a = 0;
    if (node->l) {
      node->a += node->l->a;
    }
    if (node->r) {
      node->a += node->r->a;
    }
  }

  ll query(Node *node, int nodeLow, int nodeHigh, int queryLow, int queryHigh) {
    if (node == nullptr) {
      return 0;
    }

    if (nodeLow >= queryLow && nodeHigh <= queryHigh) {
      return node->a;
    }
    if (nodeHigh < queryLow || nodeLow > queryHigh) {
      return 0;
    }
    int nodeMid = nodeLow + (nodeHigh - nodeLow) / 2;
    push(node, nodeLow, nodeHigh);
    ll left = query(node->l, nodeLow, nodeMid, queryLow, queryHigh);
    ll right = query(node->r, nodeMid + 1, nodeHigh, queryLow, queryHigh);
    return left + right;
  }
};

#define HAS_TESTCASE 0

void useOnce() {}

void solve() {
  int n;
  cin >> n;
  ll c = 0;
  LazySparseSegmentTree seg(1e9 + 5);

  for (int i = 0; i < n; i++) {
    ll type, l, r;
    cin >> type >> l >> r;
    --l, r--;
    l += c;
    r += c;
    if (type == 1) {
      c = seg.query(seg.root, 0, 1e9, l, r);
      cout << c << "\n";
    } else {
      seg.update(seg.root, 0, 1e9, l, r, 1);
    }
  }
}

int main() {
  useOnce();
  cin.tie(0)->sync_with_stdio(false);
#ifdef LOCAL_PROJECT
  freopen("error.txt", "w", stderr);
#endif
  // freopen("boards.in", "r", stdin); freopen("boards.out", "w", stdout);

  if (HAS_TESTCASE) {
    int t;
    cin >> t;
    int T = t;
    while (t--) {
      // if (t != T - 1) {
      //   FIRST_TESTCASE = false;
      // }
      // if (t == (10000 - 1722)) {
      //   CHECK_NOW = true;
      // } else {
      //   CHECK_NOW = false;
      // }
      // solve_bruteforce();
      solve();
    }
  } else {
    solve();
  }
}
#Verdict Execution timeMemoryGrader output
Fetching results...