description: Two painters, Amin and Benj, are repainting Gregor's living room ceiling! The ceiling can be modeled as an n × m grid.
  
  For each i between 1 and n, inclusive, painter Amin applies a_i layers of paint to the entire i-th row. For each j between 1 and m, inclusive, painter Benj applies b_j layers of paint to the entire j-th column. Therefore, the cell (i,j) ends up with a_i+b_j layers of paint.
  
  Gregor considers the cell (i,j) to be badly painted if a_i+b_j ≤ x. Define a badly painted region to be a maximal connected component of badly painted cells, i. e. a connected component of badly painted cells such that all adjacent to the component cells are not badly painted. Two cells are considered adjacent if they share a side.
  
  Gregor is appalled by the state of the finished ceiling, and wants to know the number of badly painted regions.
  
  Input
  
  The first line contains three integers n, m and x (1 ≤ n,m ≤ 2⋅ 10^5, 1 ≤ x ≤ 2⋅ 10^5) — the dimensions of Gregor's ceiling, and the maximum number of paint layers in a badly painted cell.
  
  The second line contains n integers a_1, a_2, …, a_n (1 ≤ a_i ≤ 2⋅ 10^5), the number of paint layers Amin applies to each row.
  
  The third line contains m integers b_1, b_2, …, b_m (1 ≤ b_j ≤ 2⋅ 10^5), the number of paint layers Benj applies to each column.
  
  Output
  
  Print a single integer, the number of badly painted regions.
  
  Examples
  
  Input
  
  
  3 4 11
  9 8 5
  10 6 7 2
  
  
  Output
  
  
  2
  
  
  Input
  
  
  3 4 12
  9 8 5
  10 6 7 2
  
  
  Output
  
  
  1
  
  
  Input
  
  
  3 3 2
  1 2 1
  1 2 1
  
  
  Output
  
  
  4
  
  
  Input
  
  
  5 23 6
  1 4 3 5 2
  2 3 1 6 1 5 5 6 1 3 2 6 2 3 1 6 1 4 1 6 1 5 5
  
  
  Output
  
  
  6
  
  Note
  
  The diagram below represents the first example. The numbers to the left of each row represent the list a, and the numbers above each column represent the list b. The numbers inside each cell represent the number of paint layers in that cell.
  
  The colored cells correspond to badly painted cells. The red and blue cells respectively form 2 badly painted regions.
  
  <image>
solution: #include <bits/stdc++.h>
  class Scanner {
   private:
    static const int BUFFER_SIZE = 1 << 18;
    char buff[BUFFER_SIZE];
    char *buffPos, *buffLim;
    FILE* file;
  
   public:
    Scanner(FILE* file) {
      this->file = file;
      buffLim = buff + fread(buff, 1, BUFFER_SIZE, file);
      buffPos = buff;
    }
  
   private:
    inline void flushBuff() {
      buffLim = buff + fread(buff, 1, BUFFER_SIZE, file);
      if (buffLim == buff) {
        *buffLim++ = '\n';
      }
      buffPos = buff;
    }
    inline bool isWS(char t) { return t <= ' '; }
    inline bool isDig(char t) { return t >= '0' && t <= '9'; }
    inline void nextPos() {
      buffPos++;
      if (buffPos == buffLim) {
        flushBuff();
      }
    }
  
   public:
    inline char getchar() {
      char ch = *buffPos;
      nextPos();
      return ch;
    }
    inline void next(char* s) {
      while (isWS(*buffPos)) {
        nextPos();
      }
      while (!isWS(*buffPos)) {
        *s = *buffPos;
        s++;
        nextPos();
      }
      *s = '\0';
    }
    inline void nextLine(char* s) {
      while (*buffPos != '\n') {
        nextPos();
      }
      if (*buffPos == '\n') {
        nextPos();
      }
      while (*buffPos != '\n') {
        *s++ = *buffPos;
        nextPos();
      }
      *s = '\0';
    }
    inline int nextInt() {
      while (!isDig(*buffPos) && *buffPos != '-') {
        nextPos();
      }
      int sign = (*buffPos == '-') ? nextPos(), -1 : 1;
      int res = 0;
      while (isDig(*buffPos)) {
        res = res * 10 + *buffPos - '0';
        nextPos();
      }
      return res * sign;
    }
    inline long long nextLong() {
      while (!isDig(*buffPos) && *buffPos != '-') {
        nextPos();
      }
      long long sign = (*buffPos == '-') ? nextPos(), -1 : 1;
      long long res = 0;
      while (isDig(*buffPos)) {
        res = res * 10 + *buffPos - '0';
        nextPos();
      }
      return res * sign;
    }
    inline int n() {
      while (*buffPos < '0' || *buffPos > '9') {
        buffPos++;
        if (buffPos == buffLim) {
          flushBuff();
        }
      }
      int res = 0;
      while (*buffPos >= '0' && *buffPos <= '9') {
        res = res * 10 + (*buffPos - '0');
        buffPos++;
        if (buffPos == buffLim) {
          flushBuff();
        }
      }
      return res;
    }
    inline long long nl() {
      while (*buffPos < '0' || *buffPos > '9') {
        buffPos++;
        if (buffPos == buffLim) {
          flushBuff();
        }
      }
      long long res = 0;
      while (*buffPos >= '0' && *buffPos <= '9') {
        res = res * 10 + (*buffPos - '0');
        buffPos++;
        if (buffPos == buffLim) {
          flushBuff();
        }
      }
      return res;
    }
    inline long long nlm(const int MOD) {
      while (*buffPos < '0' || *buffPos > '9') {
        buffPos++;
        if (buffPos == buffLim) {
          flushBuff();
        }
      }
      long long res = 0;
      while (*buffPos >= '0' && *buffPos <= '9') {
        res = (res * 10 + (*buffPos - '0')) % MOD;
        buffPos++;
        if (buffPos == buffLim) {
          flushBuff();
        }
      }
      return res;
    }
    inline double nextDouble() {
      while (isWS(*buffPos)) {
        nextPos();
      }
      int sign = (*buffPos == '-') ? nextPos(), -1 : 1;
      double res = 0;
      while (isDig(*buffPos)) {
        res = res * 10 + *buffPos - '0';
        nextPos();
      }
      if (*buffPos == '.') {
        nextPos();
        double ep = 1;
        while (isDig(*buffPos)) {
          ep *= 0.1;
          res += ep * (*buffPos - '0');
          nextPos();
        }
      }
      return sign * res;
    }
    inline char nextChar() {
      while (isWS(*buffPos)) nextPos();
      char res = *buffPos;
      nextPos();
      return res;
    }
    ~Scanner() { fclose(file); }
  };
  Scanner sc(stdin);
  template <class __TyFirst, class __TySecond>
  std::ostream& operator<<(std::ostream& out,
                           const std::pair<__TyFirst, __TySecond>& o);
  static std::string cout_list_sep = " ";
  template <
      class IterateType, typename = decltype(std::declval<IterateType>().begin()),
      typename = decltype(std::declval<IterateType>().end()),
      typename = typename std::enable_if<std::is_convertible<
          typename std::iterator_traits<
              typename IterateType::iterator>::iterator_category,
          std::input_iterator_tag>::value>::type,
      typename = typename std::enable_if<!std::is_base_of<
          std::string, typename std::decay<IterateType>::type>::value>::type,
      typename value_type = typename IterateType::value_type>
  std::ostream& operator<<(std::ostream& out, const IterateType& a) {
    for (const auto& i : a) out << i << cout_list_sep;
    return out;
  }
  template <class __TyFirst, class __TySecond>
  std::ostream& operator<<(std::ostream& out,
                           const std::pair<__TyFirst, __TySecond>& o) {
    out << "(" << o.first << "," << o.second << ")";
    return out;
  }
  template <typename _ForwardIterator>
  void logArray(_ForwardIterator, _ForwardIterator, const char* = 0) {}
  namespace Temps {
  template <typename _IntType>
  class RangeInt {
    static_assert(std::is_integral<_IntType>::value,
                  "RangeInt object must have integral value type");
  
   public:
    class iterator : public std::iterator<std::input_iterator_tag, _IntType,
                                          _IntType, const _IntType*, _IntType> {
      _IntType val, step;
  
     public:
      using typename std::iterator<std::input_iterator_tag, _IntType, _IntType,
                                   const _IntType*, _IntType>::reference;
      explicit constexpr iterator(int val, int step) noexcept
          : val(val), step(step) {}
      constexpr iterator& operator++() noexcept {
        val += step;
        return *this;
      }
      constexpr iterator operator++(int) noexcept {
        iterator ret = *this;
        val += step;
        return ret;
      }
      constexpr bool operator==(const iterator& rhs) const noexcept {
        return val == rhs.val;
      }
      constexpr bool operator!=(const iterator& rhs) const noexcept {
        return val != rhs.val;
      }
      constexpr reference operator*() const { return val; }
    };
    const _IntType _begin, _step, _end;
    explicit constexpr RangeInt(const _IntType end) noexcept
        : _begin(0), _step(1), _end(end > 0 ? end : 0) {}
    explicit constexpr RangeInt(const _IntType begin, const _IntType end) noexcept
        : _begin(begin), _step(1), _end(end > begin ? end : begin) {}
    explicit constexpr RangeInt(const _IntType begin, const _IntType end,
                                const _IntType step)
        : _begin(begin),
          _step(step),
          _end(((step > 0 && end <= begin) || (step < 0 && end >= begin))
                   ? begin
                   : (step > 0
                          ? begin + (end - begin + step - 1) / step * step
                          : begin + (begin - end - step - 1) / (-step) * step)) {}
    constexpr iterator begin() const noexcept { return iterator(_begin, _step); }
    constexpr iterator end() const noexcept { return iterator(_end, _step); }
    constexpr _IntType size() const noexcept { return (_end - _begin) / _step; }
  };
  template <class IntType, typename = typename std::enable_if<
                               std::is_integral<IntType>::value>::type>
  inline constexpr RangeInt<IntType> range(IntType arg1) {
    return RangeInt<IntType>(arg1);
  }
  template <class IntType, typename = typename std::enable_if<
                               std::is_integral<IntType>::value>::type>
  inline constexpr RangeInt<IntType> range(IntType arg1, IntType arg2) {
    return RangeInt<IntType>(arg1, arg2);
  }
  template <class IntType, typename = typename std::enable_if<
                               std::is_integral<IntType>::value>::type>
  inline constexpr RangeInt<IntType> range(IntType arg1, IntType arg2,
                                           IntType arg3) {
    return RangeInt<IntType>(arg1, arg2, arg3);
  }
  }  // namespace Temps
  using Temps::range;
  namespace Temps {
  template <class T>
  inline bool checkMin(T& a, T b) {
    return (b < a ? a = b, 1 : 0);
  }
  template <class T>
  inline bool checkMax(T& a, T b) {
    return (a < b ? a = b, 1 : 0);
  }
  template <class IntType, typename = typename std::enable_if<
                               std::is_integral<IntType>::value>::type>
  IntType gcd(const IntType a, const IntType b) {
    return b == 0 ? a : gcd(b, a % b);
  }
  template <class IntType, typename = typename std::enable_if<
                               std::is_integral<IntType>::value>::type>
  IntType lcm(const IntType a, const IntType b) {
    return a / gcd(a, b) * b;
  }
  template <class ForwardIterator, class OutputIterator>
  void dissociate(ForwardIterator __begin, ForwardIterator __end,
                  OutputIterator __dest) {
    std::vector<typename std::iterator_traits<ForwardIterator>::_IntType> values(
        __begin, __end);
    std::sort(values.begin(), values.end());
    std::unique(values.begin(), values.end());
    while (__begin != __end) {
      *__dest =
          static_cast<typename std::iterator_traits<OutputIterator>::_IntType>(
              std::distance(
                  values.begin(),
                  std::lower_bound(values.begin(), values.end(), *__begin)));
      __dest++;
      __begin++;
    }
  }
  }  // namespace Temps
  using Temps::checkMax;
  using Temps::checkMin;
  void preInit();
  void init();
  void solve();
  int32_t main() {
    preInit();
    init();
    solve();
    return 0;
  }
  template <typename T>
  struct FTree {
    size_t n;
    std::vector<T> a;
    FTree() {}
    FTree(size_t n) : n(n + 1), a(n + 2) {}
    void init(int _n) {
      n = _n + 1;
      a.resize(n + 1);
    }
    void add(size_t x, T v) {
      ++x;
      for (; x <= n; x += x & -x) a[x] += v;
    }
    T sum(size_t x) {
      ++x;
      x = std::min(x, n);
      T ret = 0;
      for (; x; x -= (x & -x)) ret += a[x];
      return ret;
    }
  };
  struct node_t {
    int a, b, t;
    bool operator<(const node_t& n) const {
      return a < n.a || (a == n.a && t < n.t);
    }
  };
  std::vector<int> calc(std::vector<int> a) {
    size_t n = a.size();
    std::vector<int> b(n, -1), c(n, -1);
    std::vector<size_t> stk(n);
    size_t tp = 0;
    for (size_t i = 0; i < n; ++i) {
      int mx = -1;
      while (tp && a[stk[tp - 1]] > a[i]) {
        mx = std::max(mx, a[stk[tp - 1]]);
        mx = std::max(mx, b[stk[tp - 1]]);
        --tp;
      }
      if (tp)
        b[i] = mx;
      else
        b[i] = 1e9;
      stk[tp++] = i;
    }
    tp = 0;
    for (size_t i = n - 1; i < n; --i) {
      int mx = -1;
      while (tp && a[stk[tp - 1]] >= a[i]) {
        mx = std::max(mx, a[stk[tp - 1]]);
        mx = std::max(mx, c[stk[tp - 1]]);
        --tp;
      }
      if (tp)
        c[i] = mx;
      else
        c[i] = 1e9;
      stk[tp++] = i;
    }
    for (size_t i = 0; i < n; ++i) checkMin(b[i], c[i]);
    return b;
  };
  std::vector<int> a, b;
  size_t n, m;
  int x;
  void preInit() {}
  void init() {
    n = (size_t)sc.n();
    m = (size_t)sc.n();
    x = sc.n();
    a.resize(n);
    b.resize(m);
    for (size_t i = 0; i < n; ++i) a[i] = std::min(sc.n(), x);
    for (size_t i = 0; i < m; ++i) b[i] = std::min(sc.n(), x);
  }
  void solve() {
    std::vector<int> c = calc(a), d = calc(b);
    std::vector<node_t> vec;
    for (size_t i = 0; i < n; ++i)
      if (c[i] > a[i]) vec.push_back({a[i], c[i], 0});
    for (size_t i = 0; i < m; ++i)
      if (d[i] > b[i]) vec.push_back({x - d[i], x - b[i], 1});
    std::sort(vec.begin(), vec.end());
    long long ans = 0;
    FTree<int> st(200005);
    for (auto& p : vec)
      if (p.t == 0) {
        ans += st.sum((size_t)p.b - 1) - st.sum((size_t)p.a - 1);
      } else {
        st.add((size_t)p.b, 1);
      }
    std::cout << ans << std::endl;
  }
  