#include <bits/stdc++.h>
using namespace std;
const int N = 1e5;
const int BLOCK_SIZE = 300;
const int M = N / BLOCK_SIZE + 1;
void Minimize(int &a, int b) {
  if (!a || (a > b && b)) a = b;
}
int Min(int a, int b) {
  Minimize(a, b);
  return a;
}
int Sum(int a, int b) { return a && b ? a + b : 0; }
class TList {
 public:
  list<pair<int, int> > a;
  long long sum = 0;
  void Insert(int x, int sign) {
    if (sign == 0) return;
    auto it = find_if(a.begin(), a.end(),
                      [&](pair<int, int> a_x) { return a_x.first >= x; });
    if (it != a.end() && it->first == x)
      it->second += sign;
    else
      a.insert(it, pair<int, int>(x, sign));
    sum += (long long)x * sign;
  }
  void Minimize(int x) {
    int old = 0;
    while (!a.empty() && a.back().first >= x) {
      old += a.back().second;
      sum += (long long)(x - a.back().first) * a.back().second;
      a.pop_back();
    }
    if (old > 0) a.push_back(pair<int, int>(x, old));
  }
  void Merge(TList &b) {
    sum += b.sum;
    auto ita = a.begin(), itb = b.a.begin();
    while (itb != b.a.end()) {
      while (ita != a.end() && ita->first < itb->first) ++ita;
      if (ita != a.end() && ita->first == itb->first)
        ita->second += itb->second;
      else
        a.insert(ita, *itb);
      ++itb;
    }
    b.clear();
  }
  int Count() {
    return accumulate(a.begin(), a.end(), 0, [](int a, pair<int, int> b) {
      a += b.second;
      return a;
    });
  }
  void clear() {
    sum = 0;
    a.clear();
  }
  void Invert() {
    sum = -sum;
    for (pair<int, int> &p : a) p.second *= -1;
  }
};
int q, a[2][N], lz[2][M], zero[M];
TList b[4][M];
inline int BlockId(int p) { return p / BLOCK_SIZE; }
int Get(int x) {
  return Sum(Min(a[0][x], lz[0][BlockId(x)]), Min(a[1][x], lz[1][BlockId(x)]));
}
long long BruteQuery(int l, int r) {
  return ({
    long long re = 0;
    while (l <= r) re += Get(l++);
    re;
  });
}
void PartialUpdate(int l, int r, int type, int v) {
  TList c[4];
  for (int i = l; i <= r; ++i) {
    int d[2] = {Min(a[0][i], lz[0][BlockId(i)]),
                Min(a[1][i], lz[1][BlockId(i)])};
    if (!d[0] && !d[1]) {
      --zero[BlockId(l)];
      c[type].Insert(v, 1);
    } else if (d[type] && !d[!type] && d[type] > v) {
      c[type].Insert(d[type], -1);
      c[type].Insert(v, 1);
    } else if (d[!type] && !d[type]) {
      c[!type].Insert(d[!type], -1);
      c[!type + 2].Insert(d[!type], 1);
      c[type + 2].Insert(v, 1);
    } else if (d[type] && d[!type] && d[type] > v) {
      c[type + 2].Insert(d[type], -1);
      c[type + 2].Insert(v, 1);
    }
    Minimize(a[type][i], v);
  }
  int id = BlockId(l);
  for (int i = 0; i < 4; ++i) b[i][id].Merge(c[i]);
}
void Update(int l, int r, int type, int v) {
  int bl = BlockId(l), br = BlockId(r);
  if (bl == br) return PartialUpdate(l, r, type, v);
  PartialUpdate(l, (bl + 1) * BLOCK_SIZE - 1, type, v);
  PartialUpdate(br * BLOCK_SIZE, r, type, v);
  for (int i = bl + 1; i < br; ++i) {
    TList &p = b[type][i], &n = b[!type][i], &nnp = b[!type + 2][i],
          &npp = b[type + 2][i];
    p.Minimize(v);
    npp.Minimize(v);
    npp.Insert(v, n.Count());
    nnp.Merge(n);
    if (zero[i]) p.Insert(v, zero[i]), zero[i] = 0;
    Minimize(lz[type][i], v);
  }
}
long long Query(int l, int r) {
  int bl = BlockId(l), br = BlockId(r);
  if (bl == br) return BruteQuery(l, r);
  long long re =
      BruteQuery(l, (bl + 1) * BLOCK_SIZE - 1) + BruteQuery(br * BLOCK_SIZE, r);
  for (int i = bl + 1; i < br; ++i) re += b[2][i].sum + b[3][i].sum;
  return re;
}
void Solve() {
  for (int i = 0; i < BlockId(N - 1); ++i) zero[i] = BLOCK_SIZE;
  zero[BlockId(N - 1)] = N - BlockId(N - 1) * BLOCK_SIZE;
  while (q--) {
    int type, l, r, k;
    scanf("%d %d %d", &type, &l, &r);
    --l, --r, --r;
    if (type == 1) {
      scanf("%d", &k);
      Update(l, r, k > 0, abs(k));
    } else
      printf("%lld\n", Query(l, r));
  }
}
int main() {
  scanf("%d", &q);
  Solve();
  return 0;
}
