#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;
// Multiset with Log(N) queries for getting element at k-th rank, and finding
// the number of elements that are at least a given threshold.
class Multiset {
  // Implemented as an AVL tree where each node keeps track of its subtree size.
 public:
  Multiset() {}

  // O(log n)
  void Insert(ll k) {
    if (root == nullptr) {
      root = make_shared<Node>(k, /*parent=*/nullptr);
      return;
    }

    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    // Found k. No need to update balances or do rotations.
    if (cur->value == k) {
      while (cur != nullptr) {
        cur->subtree_size++;
        cur = cur->parent;
      }
      return;
    }

    // Add a new node since cur wasn't in the tree.
    const bool increased_height = cur->balance == 0;
    if (k < cur->value) {
      cur->left = make_shared<Node>(k, cur);
      cur->balance--;
    } else {
      cur->right = make_shared<Node>(k, cur);
      cur->balance++;
    }
    cur->subtree_size++;

    // No need to do rotations if the new node did not increase the height of
    // its parent.
    if (!increased_height) {
      while (cur->parent != nullptr) {
        cur = cur->parent;
        cur->subtree_size++;
      }
      return;
    };

    shared_ptr<Node> parent;
    // Walk from the inserted node to the root, doing a rotation if necessary.
    // If an iteration of the while loop performs a rotation (or two), we can
    // break since no nodes further up the tree will need a rotation.
    while (cur != nullptr) {
      if (cur->balance == 0) break;
      parent = cur->parent;
      if (parent == nullptr) break;
      parent->subtree_size++;
      if (parent->left == cur) {
        parent->balance--;
        if (parent->balance == -2) {
          if (cur->balance == -1) {
            RotateRight(parent);
            break;
          } else {  // cur->balance == 1
            RotateLeft(cur);
            RotateRight(parent);
            cur = cur->parent;
            break;
          }
        }
      } else {
        parent->balance++;
        if (parent->balance == 2) {
          if (cur->balance == 1) {
            RotateLeft(parent);
            break;
          } else {  // cur->balance == -1
            RotateRight(cur);
            RotateLeft(parent);
            cur = cur->parent;
            break;
          }
        }
      }
      cur = parent;
    }

    do {
      cur = cur->parent;
      if (cur == nullptr) break;
      cur->subtree_size++;
    } while (cur != nullptr);
  }

  // Removes one instance of k from the Multiset. Does nothing if t is not
  // present. O(log N)
  void Delete(ll k) {
    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    if (cur->value != k) return;  // k was not present.
    if (cur->subtree_size >
        1 + SubtreeSize(cur->left) + SubtreeSize(cur->right)) {
      // No nodes need to be removed.
      while (cur != nullptr) {
        cur->subtree_size--;
        cur = cur->parent;
      }
      return;
    }

    // Invariants: One of rebalance_node's children has had one of its child
    // subtrees' heights lowered by one. (However, rebalance_node may be
    // nullptr, in which case there will be nothing left to update.
    // left_subtree_shrunk boolean helps keep track of which one it is.
    shared_ptr<Node> rebalance_node;
    bool left_subtree_shrunk;
    // Delete the node. subtree_size's and balances in the tree at cur or above
    // may become outdated.
    if (cur->left == nullptr && cur->right == nullptr) {
      // Case 1: cur has no children.
      if (cur->parent != nullptr) {
        rebalance_node = cur->parent;
        left_subtree_shrunk = cur->parent->left == cur;
      }
      DeleteChildlessNode(cur);
    } else if (cur->left == nullptr || cur->right == nullptr) {
      // Case 2: cur has exactly one child.
      if (cur->parent != nullptr) {
        rebalance_node = cur->parent;
        left_subtree_shrunk = cur->parent->left == cur;
      }
      MoveChildInto(cur);
    } else {
      // Case 3: cur has two children.
      left_subtree_shrunk = cur->left->right != nullptr;
      rebalance_node = MoveInorderSuccessorInto(cur);
    }

    // Then, for all three cases above, start at the smallest subtree with its
    // height decreased by one. Trace up the tree, while updating all data
    // structures and making sure all balances are within [-1, 1].
    // Invariant: Upon loop start, rebalance_node's balance and subtree_size are
    // outdated, but all balances and subtree_size's under it are correct.
    while (rebalance_node != nullptr) {
      rebalance_node->subtree_size--;
      // Save parent because some rotations might happen.
      shared_ptr<Node> parent = rebalance_node->parent;
      bool new_left_subtree_shrunk;
      if (parent != nullptr)
        new_left_subtree_shrunk = parent->left == rebalance_node;
      if (left_subtree_shrunk) {
        rebalance_node->balance++;  // This balance is now in [0, 2].
        if (rebalance_node->balance == 2) {
          shared_ptr<Node> child = rebalance_node->right;
          if (child->balance < 0) {
            RotateRight(child);
            RotateLeft(rebalance_node);
          } else {
            RotateLeft(rebalance_node);
          }
        } else if (rebalance_node->balance == 1) {
          rebalance_node->balance = 1;
          break;
        } else {  // rebalance_node->balance == 0
          rebalance_node->balance = 0;
          continue;
        }
      } else {                      // right subtree shrunk
        rebalance_node->balance--;  // This balance is now in [-2, 0].
        if (rebalance_node->balance == -2) {
          shared_ptr<Node> child = rebalance_node->left;
          if (child->balance > 0) {
            RotateLeft(child);
            RotateRight(rebalance_node);
          } else {
            RotateRight(rebalance_node);
          }
        } else if (rebalance_node->balance == -1) {
          rebalance_node->balance = -1;
          break;
        } else {  // rebalance_node->balance == 0
          rebalance_node->balance = 0;
          continue;
        }
      }
      rebalance_node = parent;
      left_subtree_shrunk = new_left_subtree_shrunk;
    }
  }

  // O(log N)
  ll CountNumAtLeast(ll t) { return CountNumAtLeast(t, root); }

 private:
  struct Node {
    explicit Node(ll v, shared_ptr<Node> p) : value(v), parent(p) {}
    int subtree_size = 1;
    // Equals height(right subtree) - height(left subtree).
    // Can be -2 or +2 during intermediate stages.
    int balance = 0;
    ll value;
    shared_ptr<Node> left;
    shared_ptr<Node> right;
    shared_ptr<Node> parent;
  };

  // Convenience function for getting the subtree_size of a possibly null Node.
  ll SubtreeSize(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return n->subtree_size;
  }

  ll CountNumAtLeast(ll t, shared_ptr<Node> n) {
    const int n_left_subtree_size = SubtreeSize(n->left);
    if (n->value == t) return n->subtree_size - n_left_subtree_size;
    if (n->value > t) {
      if (n->left == nullptr)
        return n->subtree_size;
      else
        return n->subtree_size - n_left_subtree_size +
               CountNumAtLeast(t, n->left);
    }
    if (n->right == nullptr) return 0;
    return CountNumAtLeast(t, n->right);
  }

  // Does not update balances or subtree_size's above x.
  void DeleteChildlessNode(shared_ptr<Node> x) {
    if (x->parent == nullptr) {  // x is the root
      root = nullptr;
      return;
    }
    shared_ptr<Node> parent = x->parent;
    if (parent->left == x)
      parent->left == nullptr;
    else
      parent->right == nullptr;
  }

  // Preconditions: n has exactly child. Note that x's child must be childless.
  // Does not update: 1) balances at x or above, 2) subtree_size's above x.
  void MoveChildInto(shared_ptr<Node> x) {
    if (x == root) {
      if (x->left != nullptr) {
        x->left->parent = nullptr;
        root = x->left;
      } else {
        x->right->parent = nullptr;
        root = x->right;
      }
      return;
    }
    shared_ptr<Node> child = x->left == nullptr ? x->right : x->left;
    x->value = child->value;
    x->subtree_size = child->subtree_size;
    if (child == x->left)
      x->left = nullptr;
    else
      x->right = nullptr;
  }

  // Does not update: 1) balances at inorder successor or above, 2)
  // subtree_size's above x.
  // At the end of this function,the returned Node and all ancestor Nodes
  // will have a subtree_size that is exactly one more than it should be.
  // Returns the parent of the inorder successor's Node (before moving it).
  shared_ptr<Node> MoveInorderSuccessorInto(shared_ptr<Node> x) {
    shared_ptr<Node> successor = x->right;
    while (successor->left != nullptr) successor = successor->left;
    shared_ptr<Node> successor_original_parent = successor->parent;

    int old_successor_subtree_size = successor->subtree_size;  // 0 or 1
    // Copy the successor data into x.
    x->value = successor->value;
    x->subtree_size = old_successor_subtree_size + x->left->subtree_size +
                      x->right->subtree_size;
    // Update the subtree sizes of all nodes in between the current and old
    // successor nodes (to account for the swap.)
    shared_ptr<Node> nodes_from_successor_to_x = successor->parent;
    while (nodes_from_successor_to_x != x) {
      nodes_from_successor_to_x->subtree_size -= old_successor_subtree_size;
      nodes_from_successor_to_x = nodes_from_successor_to_x->parent;
    }

    // Delete old the successor node.
    if (successor->right == nullptr)
      DeleteChildlessNode(successor);  // successor cannot have a left child
    else
      MoveChildInto(successor);

    return successor_original_parent;
  }

  // In the Rotate* functions below, x is the root of the old subtree.
  // Preconditions: balances and counts at x and under must be accurate.
  // Postconditions: balances and counts at x and under will be accurate.
  //
  // x and x->right must be non-null. x->left may be null and x->right may be a
  // leaf. x should have balance +1 or +2.
  void RotateLeft(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->left) - x->right->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->right;
    shared_ptr<Node> t = z->left;
    if (root == x) root = z;
    x->right = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;

    if (x->parent != nullptr) {
      if (x == x->parent->left)
        x->parent->left = z;
      else
        x->parent->right = z;
    }
    z->left = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if (x->balance == z->balance)
      x->balance = -1;
    else
      x->balance = 0;
    if (old_x_balance == 2)
      z->balance = 0;
    else if (z->balance >= 0)
      z->balance = -1;
    else
      z->balance = -2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
  }

  // x and x->left must be non-null. x->right may be null and x->left may be a
  // leaf. x should have balance -1 or -2.
  void RotateRight(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->right) - x->left->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->left;
    shared_ptr<Node> t = z->right;
    if (root == x) root = z;
    x->left = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;
    if (x->parent != nullptr) {
      if (x == x->parent->right)
        x->parent->right = z;
      else
        x->parent->left = z;
    }
    z->right = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if (x->balance == z->balance)
      x->balance = 1;
    else
      x->balance = 0;
    if (old_x_balance == -2)
      z->balance = 0;
    else if (z->balance <= 0)
      z->balance = 1;
    else
      z->balance = 2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
  }

  shared_ptr<Node> root;
};

int n;
ll t;
vector<ll> a;

void Load() {
  scanf("%d%lld", &n, &t);
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lld", &a[i]);
  }
}

void Solve() {
  vector<ll> pref(n, 0);
  pref[0] = a[0];
  for (int i = 1; i < n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }

  Multiset multiset;
  multiset.Insert(0);
  ll ans = 0, segment_max = t - 1;
  for (int i = 0; i < n; ++i) {
    ll min_pref_sum = pref[i] - segment_max;
    ans += multiset.CountNumAtLeast(min_pref_sum);
    multiset.Insert(pref[i]);
  }
  printf("%lld\n", ans);
}

int main() {
  Load();
  Solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

/* BEGIN LIBRARIES */

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

/* BEGIN LIBRARIES */

// Multiset with Log(N) queries for getting element at k-th rank, and finding
// the number of elements that are at least a given threshold.
class Multiset {
  // Implemented as an AVL tree where each node keeps track of its subtree size.
 public:
  Multiset() {}

  void Insert(ll k) {
    if (root == nullptr) {
      root = make_shared<Node>(k, /*parent=*/nullptr);
      return;
    }

    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    // Found k. No need to update balances or do rotations.
    if (cur->value == k) {
      while (cur != nullptr) {
        cur->subtree_size++;
        cur = cur->parent;
      }
      return;
    }

    // Add a new node since cur wasn't in the tree.
    const bool increased_height = cur->balance == 0;
    if (k < cur->value) {
      cur->left = make_shared<Node>(k, cur);
      cur->balance--;
    } else {
      cur->right = make_shared<Node>(k, cur);
      cur->balance++;
    }
    cur->subtree_size++;

    // No need to do rotations if the new node did not increase the height of
    // its parent.
    if (!increased_height) {
      while (cur->parent != nullptr) {
        cur = cur->parent;
        cur->subtree_size++;
      }
      return;
    };

    shared_ptr<Node> parent;
    // Walk from the inserted node to the root, doing a rotation if necessary.
    // If an iteration of the while loop performs a rotation (or two), we can
    // break since no nodes further up the tree will need a rotation.
    while (cur != nullptr) {
      if (cur->balance == 0) break;
      parent = cur->parent;
      if (parent == nullptr) break;
      parent->subtree_size++;
      if (parent->left == cur) {
        parent->balance--;
        if (parent->balance == -2) {
          if (cur->balance == -1) {
            RotateRight(parent);
            break;
          } else {  // cur->balance == 1
            RotateLeft(cur);
            RotateRight(parent);
            cur = cur->parent;
            break;
          }
        }
      } else {
        parent->balance++;
        if (parent->balance == 2) {
          if (cur->balance == 1) {
            RotateLeft(parent);
            break;
          } else {  // cur->balance == -1
            RotateRight(cur);
            RotateLeft(parent);
            cur = cur->parent;
            break;
          }
        }
      }
      cur = parent;
    }

    do {
      cur = cur->parent;
      if (cur == nullptr) break;
      cur->subtree_size++;
    } while (cur != nullptr);
  }

  // Removes one instance of k from the Multiset. Does nothing if t is not
  // present. O(log N)
  void Delete(ll k) {
    if (root == nullptr) return;
    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    if (cur->value != k) return;  // k was not present.
    if (cur->subtree_size >
        1 + SubtreeSize(cur->left) + SubtreeSize(cur->right)) {
      // No nodes need to be removed.
      while (cur != nullptr) {
        cur->subtree_size--;
        cur = cur->parent;
      }
      return;
    }

    // Invariants: One of rebalance_node's children has had one of its child
    // subtrees' heights lowered by one. (However, rebalance_node may be
    // nullptr, in which case there will be nothing left to update.
    // left_subtree_shrunk boolean helps keep track of which one it is.
    shared_ptr<Node> rebalance_node;
    bool left_subtree_shrunk;
    // Delete the node. subtree_size's and balances in the tree at cur or above
    // may become outdated.
    if (cur->left == nullptr && cur->right == nullptr) {
      // Case 1: cur has no children.
      if (cur->parent != nullptr) {
        rebalance_node = cur->parent;
        left_subtree_shrunk = cur->parent->left == cur;
      }
      DeleteChildlessNode(cur);
    } else if (cur->left == nullptr || cur->right == nullptr) {
      // Case 2: cur has exactly one child.
      if (cur->parent != nullptr) {
        rebalance_node = cur->parent;
        left_subtree_shrunk = cur->parent->left == cur;
      }
      MoveChildInto(cur);
    } else {
      // Case 3: cur has two children.
      left_subtree_shrunk = cur->right->left != nullptr;
      rebalance_node = MoveInorderSuccessorInto(cur);
    }

    // Then, for all three cases above, start at the smallest subtree with its
    // height decreased by one. Trace up the tree, while updating all data
    // structures and making sure all balances are within [-1, 1].
    // Invariant: Upon loop start, rebalance_node's balance and subtree_size are
    // outdated, but all balances and subtree_size's under it are correct.
    while (rebalance_node != nullptr) {
      rebalance_node->subtree_size--;
      // Save parent because some rotations might happen.
      shared_ptr<Node> parent = rebalance_node->parent;
      bool new_left_subtree_shrunk;
      if (parent != nullptr)
        new_left_subtree_shrunk = parent->left == rebalance_node;
      if (left_subtree_shrunk) {
        rebalance_node->balance++;  // This balance is now in [0, 2].
        if (rebalance_node->balance == 2) {
          shared_ptr<Node> child = rebalance_node->right;
          if (child->balance < 0) {
            RotateRight(child);
            RotateLeft(rebalance_node);
          } else {
            RotateLeft(rebalance_node);
          }
        } else if (rebalance_node->balance == 1) {
          rebalance_node->balance = 1;
          rebalance_node = rebalance_node->parent;
          while (rebalance_node != nullptr) {
            rebalance_node->subtree_size--;
            rebalance_node = rebalance_node->parent;
          }
          break;
        } else {  // rebalance_node->balance == 0
          rebalance_node->balance = 0;
        }
      } else {                      // right subtree shrunk
        rebalance_node->balance--;  // This balance is now in [-2, 0].
        if (rebalance_node->balance == -2) {
          shared_ptr<Node> child = rebalance_node->left;
          if (child->balance > 0) {
            RotateLeft(child);
            RotateRight(rebalance_node);
          } else {
            RotateRight(rebalance_node);
          }
        } else if (rebalance_node->balance == -1) {
          rebalance_node->balance = -1;
          rebalance_node = rebalance_node->parent;
          while (rebalance_node != nullptr) {
            rebalance_node->subtree_size--;
            rebalance_node = rebalance_node->parent;
          }
          break;
        } else {  // rebalance_node->balance == 0
          rebalance_node->balance = 0;
        }
      }
      rebalance_node = parent;
      left_subtree_shrunk = new_left_subtree_shrunk;
    }
  }

  // O(log N)
  ll CountNumAtLeast(ll t) { return CountNumAtLeast(t, root); }
  ll Size() { return SubtreeSize(root); }
  ll Count(ll t) { return Count(t, root); }

 private:
  struct Node {
    explicit Node(ll v, shared_ptr<Node> p) : value(v), parent(p) {}
    int subtree_size = 1;
    // Equals height(right subtree) - height(left subtree).
    // Can be -2 or +2 during intermediate stages.
    int balance = 0;
    ll value;
    shared_ptr<Node> left;
    shared_ptr<Node> right;
    shared_ptr<Node> parent;
  };

  // Convenience function for getting the subtree_size of a possibly null Node.
  ll SubtreeSize(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return n->subtree_size;
  }

  ll CountNumAtLeast(ll t, shared_ptr<Node> n) {
    const int n_left_subtree_size = SubtreeSize(n->left);
    if (n->value == t) return n->subtree_size - n_left_subtree_size;
    if (n->value > t) {
      if (n->left == nullptr)
        return n->subtree_size;
      else
        return n->subtree_size - n_left_subtree_size +
               CountNumAtLeast(t, n->left);
    }
    if (n->right == nullptr) return 0;
    return CountNumAtLeast(t, n->right);
  }

  // n may be nullptr
  ll Count(ll t, shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    if (n->value == t)
      return SubtreeSize(n) - SubtreeSize(n->left) - SubtreeSize(n->right);
    if (n->value > t)
      return Count(t, n->left);
    else
      return Count(t, n->right);
  }

  ll Count(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return SubtreeSize(n) - SubtreeSize(n->left) - SubtreeSize(n->right);
  }

  // Does not update balances or subtree_size's above x.
  void DeleteChildlessNode(shared_ptr<Node> x) {
    if (x == root) {
      root = nullptr;
      return;
    }
    shared_ptr<Node> parent = x->parent;  // cannot be nullptr
    if (parent->left == x)
      parent->left = nullptr;
    else
      parent->right = nullptr;
  }

  // Preconditions: n has exactly child. Note that x's child must be childless.
  // Does not update: 1) balances at x or above, 2) subtree_size's above x.
  void MoveChildInto(shared_ptr<Node> x) {
    if (x == root) {
      if (x->left != nullptr) {
        x->left->parent = nullptr;
        root = x->left;
      } else {
        x->right->parent = nullptr;
        root = x->right;
      }
      return;
    }
    shared_ptr<Node> child = x->left == nullptr ? x->right : x->left;
    x->value = child->value;
    x->subtree_size = child->subtree_size;
    if (child == x->left)
      x->left = nullptr;
    else
      x->right = nullptr;
  }

  // Does not update: 1) balances at inorder successor or above, 2)
  // subtree_size's above x.
  // At the end of this function,the returned Node and all ancestor Nodes
  // will have a subtree_size that is exactly one more than it should be.
  // Returns the parent of the inorder successor's Node (before moving it).
  shared_ptr<Node> MoveInorderSuccessorInto(shared_ptr<Node> x) {
    shared_ptr<Node> successor = x->right;
    while (successor->left != nullptr) successor = successor->left;
    shared_ptr<Node> successor_original_parent = successor->parent;

    int old_successor_count = Count(successor);  // 0 or 1
    // Copy the successor data into x.
    x->value = successor->value;
    x->subtree_size =
        old_successor_count + x->left->subtree_size + x->right->subtree_size;
    // Update the subtree sizes of all nodes in between the current and old
    // successor nodes (to account for the swap.)
    shared_ptr<Node> nodes_from_successor_to_x = successor->parent;
    while (nodes_from_successor_to_x != x) {
      nodes_from_successor_to_x->subtree_size -= (old_successor_count - 1);
      nodes_from_successor_to_x = nodes_from_successor_to_x->parent;
    }

    // Delete old the successor node.
    if (successor->right == nullptr)
      DeleteChildlessNode(successor);  // successor cannot have a left child
    else
      MoveChildInto(successor);

    return successor_original_parent;
  }

  // In the Rotate* functions below, x is the root of the old subtree.
  // Preconditions: balances and counts at x and under must be accurate.
  // Postconditions: balances and counts at x and under will be accurate.
  //
  // x and x->right must be non-null. x->left may be null and x->right may be a
  // leaf. x should have balance +1 or +2.
  void RotateLeft(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->left) - x->right->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->right;
    shared_ptr<Node> t = z->left;
    if (root == x) root = z;
    x->right = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;

    if (x->parent != nullptr) {
      if (x == x->parent->left)
        x->parent->left = z;
      else
        x->parent->right = z;
    }
    z->left = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if ((x->balance == 1 && z->balance == 1) ||
        (x->balance == 2 && z->balance == 2))
      x->balance = -1;
    else
      x->balance = 0;
    if (old_x_balance == 2)
      z->balance = 0;
    else if (z->balance >= 0)
      z->balance = -1;
    else
      z->balance = -2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
  }

  // x and x->left must be non-null. x->right may be null and x->left may be a
  // leaf. x should have balance -1 or -2.
  void RotateRight(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->right) - x->left->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->left;
    shared_ptr<Node> t = z->right;
    if (root == x) root = z;
    x->left = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;
    if (x->parent != nullptr) {
      if (x == x->parent->right)
        x->parent->right = z;
      else
        x->parent->left = z;
    }
    z->right = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if ((x->balance == -1 && z->balance == -1) ||
        (x->balance == -2 && z->balance == -2))
      x->balance = 1;
    else {
      // ERROR this is incorrect now.
      x->balance = 0;
    }
    if (old_x_balance == -2)
      z->balance = 0;
    else if (z->balance <= 0)
      z->balance = 1;
    else
      z->balance = 2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
  }

  shared_ptr<Node> root;
};
/* END LIBRARIES */

int n;
ll t;
vector<ll> a;

void Load() {
  scanf("%d%lld", &n, &t);
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lld", &a[i]);
  }
}

void Solve() {
  vector<ll> pref(n, 0);
  pref[0] = a[0];
  for (int i = 1; i < n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }

  Multiset multiset;
  multiset.Insert(0);
  ll ans = 0, segment_max = t - 1;
  for (int i = 0; i < n; ++i) {
    ll min_pref_sum = pref[i] - segment_max;
    ans += multiset.CountNumAtLeast(min_pref_sum);
    multiset.Insert(pref[i]);
  }
  printf("%lld\n", ans);
}

int main() {
  Load();
  Solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

// Multiset with Log(N) queries for getting element at k-th rank, and finding
// the number of elements that are at least a given threshold.
class Multiset {
  // Implemented as an AVL tree where each node keeps track of its subtree size.
 public:
  Multiset() {}

  // O(log n)
  void Insert(ll k) {
    if (root == nullptr) {
      root = make_shared<Node>(k, /*parent=*/nullptr);
      return;
    }

    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    // Found k. No need to update balances or do rotations.
    if (cur->value == k) {
      while (cur != nullptr) {
        cur->subtree_size++;
        cur = cur->parent;
      }
      return;
    }

    // Add a new node since cur wasn't in the tree.
    const bool increased_height = cur->balance == 0;
    if (k < cur->value) {
      cur->left = make_shared<Node>(k, cur);
      cur->balance--;
    } else {
      cur->right = make_shared<Node>(k, cur);
      cur->balance++;
    }
    cur->subtree_size++;

    // No need to do rotations if the new node did not increase the height of
    // its parent.
    if (!increased_height) {
      while (cur->parent != nullptr) {
        cur = cur->parent;
        cur->subtree_size++;
      }
      return;
    };

    shared_ptr<Node> parent;
    // Walk from the inserted node to the root, doing a rotation if necessary.
    // If an iteration of the while loop performs a rotation (or two), we can
    // break since no nodes further up the tree will need a rotation.
    while (cur != nullptr) {
      if (cur->balance == 0) break;
      parent = cur->parent;
      if (parent == nullptr) break;
      parent->subtree_size++;
      if (parent->left == cur) {
        parent->balance--;
        if (parent->balance == -2) {
          if (cur->balance == -1) {
            RotateRight(parent);
            break;
          } else {  // cur->balance == 1
            RotateLeft(cur);
            RotateRight(parent);
            cur = cur->parent;
            break;
          }
        }
      } else {
        parent->balance++;
        if (parent->balance == 2) {
          if (cur->balance == 1) {
            RotateLeft(parent);
            break;
          } else {  // cur->balance == -1
            RotateRight(cur);
            RotateLeft(parent);
            cur = cur->parent;
            break;
          }
        }
      }
      cur = parent;
    }

    do {
      cur = cur->parent;
      if (cur == nullptr) break;
      cur->subtree_size++;
    } while (cur != nullptr);
  }

  // Removes one instance of k from the Multiset. Does nothing if t is not
  // present. O(log N)
  void Delete(ll k) {
    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    if (cur->value != k) return;  // k was not present.
    if (cur->subtree_size >
        1 + SubtreeSize(cur->left) +
            SubtreeSize(cur->right)) {  // No nodes need to be removed.
      while (cur != nullptr) {
        cur->subtree_size--;
        cur = cur->parent;
      }
      return;
    }

    if (cur->left == nullptr && cur->right == nullptr) {
      // Case 1: If cur has no children, remove it.
      if (cur->parent == nullptr) {  // cur is the root
        root = nullptr;
        return;
      }
      shared_ptr<Node> parent = cur->parent;
      if (parent->left == cur)
        parent->left == nullptr;
      else
        parent->right == nullptr;
    } else if (cur->left == nullptr || cur->right == nullptr) {
      // Case 2: If cur has one child, replace it with its child.
      if (cur->parent == nullptr) {  // cur is the root
        if (cur->left != nullptr) {
          cur->left->parent = nullptr;
          root = cur->left;
        } else {
          cur->right->parent = nullptr;
          root = cur->right;
        }
      }
      shared_ptr<Node> parent = cur->parent;
      shared_ptr<Node> child = cur->left == nullptr ? cur->right : cur->left;
      if (parent->left == cur)
        parent->left = child;
      else
        parent->right = child;
      child->parent = parent;
    } else {
      // Case 3: If cur has two children, move its inorder successor s into its
      // spot and then delete the node previously belonging to s.
      shared_ptr<Node> successor = cur->right;
      while (successor->left != nullptr) successor = successor->left;

      int old_successor_subtree_size = successor->subtree_size;
      // Copy the successor data into cur.
      cur->value = successor->value;
      cur->subtree_size = old_successor_subtree_size + cur->left->subtree_size +
                          cur->right->subtree_size;
      // Delete old the successor node.
      if (successor->right == nullptr) {
        // Successor has no children (since it definitely has no left child.)
        shared_ptr<Node> s_parent = successor->parent;
        if (s_parent->left == successor)
          s_parent->left = nullptr;
        else
          s_parent->right = nullptr;
      } else {
        // Successor has a right child, and it is its only child. Replace it
        // with its child.
        successor->value = successor->right->value;
        successor->subtree_size = successor->right->subtree_size;
        successor->right = nullptr;
      }
      // Update the subtree sizes of all nodes in between the current and old
      // successor nodes.
      shared_ptr<Node> nodes_from_successor_to_cur = successor->parent;
      while (nodes_from_successor_to_cur != cur) {
        nodes_from_successor_to_cur->subtree_size -= old_successor_subtree_size;
        nodes_from_successor_to_cur = nodes_from_successor_to_cur->parent;
      }
    }

    /* Then, for all three cases above, start at the smallest subtree with its
     height decreased by one. Trace up the tree, while updating all data
     structures and making sure all balances are within [-1, 1].*/
  }

  // O(log N)
  ll CountNumAtLeast(ll t) { return CountNumAtLeast(t, root); }

 private:
  struct Node {
    explicit Node(ll v, shared_ptr<Node> p) : value(v), parent(p) {}
    int subtree_size = 1;
    // Always equal to height(right subtree) - height(left subtree).
    // Can be -2 or +2 during intermediate stages.
    int balance = 0;
    ll value;
    shared_ptr<Node> left;
    shared_ptr<Node> right;
    shared_ptr<Node> parent;
  };

  // Convenience function for getting the subtree_size of a possibly null Node.
  ll SubtreeSize(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return n->subtree_size;
  }

  ll CountNumAtLeast(ll t, shared_ptr<Node> n) {
    const int n_left_subtree_size = SubtreeSize(n->left);
    if (n->value == t) return n->subtree_size - n_left_subtree_size;
    if (n->value > t) {
      if (n->left == nullptr)
        return n->subtree_size;
      else
        return n->subtree_size - n_left_subtree_size +
               CountNumAtLeast(t, n->left);
    }
    if (n->right == nullptr) return 0;
    return CountNumAtLeast(t, n->right);
  }

  // In the Rotate* functions below, x is the root of the old subtree, and
  // they both return the new subtree root.
  //
  // x and x->right must be non-null. x->left may be null and x->right may be a
  // leaf. x should have balance +1 or +2.
  shared_ptr<Node> RotateLeft(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->left) - x->right->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->right;
    shared_ptr<Node> t = z->left;
    if (root == x) root = z;
    x->right = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;

    if (x->parent != nullptr) {
      if (x == x->parent->left)
        x->parent->left = z;
      else
        x->parent->right = z;
    }
    z->left = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if (x->balance == z->balance)
      x->balance = -1;
    else
      x->balance = 0;
    if (old_x_balance == 2)
      z->balance = 0;
    else if (z->balance >= 0)
      z->balance = -1;
    else
      z->balance = -2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
    return z;
  }

  // x and x->left must be non-null. x->right may be null and x->left may be a
  // leaf. x should have balance -1 or -2.
  shared_ptr<Node> RotateRight(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->right) - x->left->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->left;
    shared_ptr<Node> t = z->right;
    if (root == x) root = z;
    x->left = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;
    if (x->parent != nullptr) {
      if (x == x->parent->right)
        x->parent->right = z;
      else
        x->parent->left = z;
    }
    z->right = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if (x->balance == z->balance)
      x->balance = 1;
    else
      x->balance = 0;
    if (old_x_balance == -2)
      z->balance = 0;
    else if (z->balance <= 0)
      z->balance = 1;
    else
      z->balance = 2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
    return z;
  }

  shared_ptr<Node> root;
};

int n;
ll t;
vector<ll> a;

void Load() {
  scanf("%d%lld", &n, &t);
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lld", &a[i]);
  }
}

void Solve() {
  vector<ll> pref(n, 0);
  pref[0] = a[0];
  for (int i = 1; i < n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }

  Multiset multiset;
  multiset.Insert(0);
  ll ans = 0, segment_max = t - 1;
  for (int i = 0; i < n; ++i) {
    ll min_pref_sum = pref[i] - segment_max;
    ans += multiset.CountNumAtLeast(min_pref_sum);
    multiset.Insert(pref[i]);
  }
  printf("%lld\n", ans);
}

int main() {
  Load();
  Solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

// Multiset with Log(N) queries for getting element at k-th rank, and finding
// the number of elements that are at least a given threshold.
class Multiset {
  // Implemented as an AVL tree where each node keeps track of its subtree size.
 public:
  Multiset() {}

  // O(log n)
  void Insert(ll k) {
    if (root == nullptr) {
      root = make_shared<Node>(k, /*parent=*/nullptr);
      return;
    }

    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    // Found k. No need to update balances or do rotations.
    if (cur->value == k) {
      while (cur != nullptr) {
        cur->subtree_size++;
        cur = cur->parent;
      }
      return;
    }

    // Add a new node since cur wasn't in the tree.
    const bool increased_height = cur->balance == 0;
    if (k < cur->value) {
      cur->left = make_shared<Node>(k, cur);
      cur->balance--;
    } else {
      cur->right = make_shared<Node>(k, cur);
      cur->balance++;
    }
    cur->subtree_size++;

    // No need to do rotations if the new node did not increase the height of
    // its parent.
    if (!increased_height) {
      while (cur->parent != nullptr) {
        cur = cur->parent;
        cur->subtree_size++;
      }
      return;
    };

    shared_ptr<Node> parent;
    // Walk from the inserted node to the root, doing a rotation if necessary.
    // If an iteration of the while loop performs a rotation (or two), we can
    // break since no nodes further up the tree will need a rotation.
    while (cur != nullptr) {
      if (cur->balance == 0) break;
      parent = cur->parent;
      if (parent == nullptr) break;
      parent->subtree_size++;
      if (parent->left == cur) {
        parent->balance--;
        if (parent->balance == -2) {
          if (cur->balance == -1) {
            RotateRight(parent);
            break;
          } else {  // cur->balance == 1
            RotateLeft(cur);
            RotateRight(parent);
            cur = cur->parent;
            break;
          }
        }
      } else {
        parent->balance++;
        if (parent->balance == 2) {
          if (cur->balance == 1) {
            RotateLeft(parent);
            break;
          } else {  // cur->balance == -1
            RotateRight(cur);
            RotateLeft(parent);
            cur = cur->parent;
            break;
          }
        }
      }
      cur = parent;
    }

    do {
      cur = cur->parent;
      if (cur == nullptr) break;
      cur->subtree_size++;
    } while (cur != nullptr);
  }

  // Removes one instance of k from the Multiset. Does nothing if t is not
  // present. O(log N)
  void Delete(ll k) {
    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    if (cur->value != k) return;  // k was not present.
    if (cur->subtree_size >
        1 + (cur->left == nullptr ? 0 : cur->left->subtree_size) +
            (cur->right == nullptr
                 ? 0
                 : cur->right->subtree_size)) {  // No nodes need to be removed.
      while (cur != nullptr) {
        cur->subtree_size cur = cur->parent;
      }
      return;
    }

    if (cur->left == nullptr && cur->right == nullptr) {
      // Case 1: If cur has no children, remove it.
      if (cur->parent == nullptr) {  // cur is the root
        root = nullptr;
        return;
      }
      shared_ptr<Node> parent = cur->parent;
      if (parent->left == cur)
        parent->left == nullptr;
      else
        parent->right == nullptr;
    } else if (cur->left == nullptr || cur->right == nullptr) {
      // Case 2: If cur has one child, replace it with its child.
      if (cur->parent == nullptr) {  // cur is the root
        if (cur->left != nullptr) {
          cur->left->parent = nullptr;
          root = cur->left;
        } else {
          cur->right->parent = nullptr;
          root = cur->right;
        }
      }
      shared_ptr<Node> parent = cur->parent;
      shared_ptr<Node> child = cur->left == nullptr ? cur->right : cur->left;
      if (parent->left == cur)
        parent->left = child;
      else
        parent->right = child;
      child->parent = parent;
    } else {
      // Case 3: If cur has two children, move its inorder successor s into its
      // spot and then delete the node previously belonging to s.
      shared_ptr<Node> successor = cur->right;
      while (successor->left != nullptr) successor = successor_left;

      int old_successor_subtree_size = successor->subtree_size;
      // Copy the successor data into cur.
      cur->value = successor->value;
      cur->subtree_size = old_successor_subtree_size + cur->left->subtree_size +
                          cur->right->subtree_size;
      // Delete old the successor node.
      if (successor->right == nullptr) {
        // Successor has no children (since it definitely has no left child.)
        shared_ptr<Node> s_parent = successor->parent;
        if (s_parent->left == successor)
          s_parent->left = nullptr;
        else
          s_parent->right = nullptr;
      } else {
        // Successor has a right child, and it is its only child. Replace it
        // with its child.
        successor->value = successor->right->value;
        successor->count = successor->right->count;
        successor->right = nullptr;
      }
      // Update the subtree sizes of all nodes in between the current and old
      // successor nodes.
      shared_ptr<Node> nodes_from_successor_to_cur = successor->parent;
      while (nodes_from_successor_to_cur != cur) {
        nodes_from_successor_to_cur->count -= old_successor_subtree_size;
        nodes_from_successor_to_cur = nodes_from_successor_to_cur->parent;
      }
    }

    /* Then, for all three cases above, start at the smallest subtree with its
     height decreased by one. Trace up the tree, while updating all data
     structures and making sure all balances are within [-1, 1].*/
  }

  // O(log N)
  ll CountNumAtLeast(ll t) { return CountNumAtLeast(t, root); }

 private:
  struct Node {
    explicit Node(ll v, shared_ptr<Node> p) : value(v), parent(p) {}
    int subtree_size = 1;
    // Always equal to height(right subtree) - height(left subtree).
    // Can be -2 or +2 during intermediate stages.
    int balance = 0;
    ll value;
    shared_ptr<Node> left;
    shared_ptr<Node> right;
    shared_ptr<Node> parent;
  };

  // Convenience function for getting the subtree_size of a possibly null Node.
  ll SubtreeSize(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return n->subtree_size;
  }

  ll CountNumAtLeast(ll t, shared_ptr<Node> n) {
    const int n_left_subtree_size = SubtreeSize(n->left);
    if (n->value == t) return n->subtree_size - n_left_subtree_size;
    if (n->value > t) {
      if (n->left == nullptr)
        return n->subtree_size;
      else
        return n->subtree_size - n_left_subtree_size +
               CountNumAtLeast(t, n->left);
    }
    if (n->right == nullptr) return 0;
    return CountNumAtLeast(t, n->right);
  }

  // In the Rotate* functions below, x is the root of the old subtree, and
  // they both return the new subtree root.
  //
  // x and x->right must be non-null. x->left may be null and x->right may be a
  // leaf. x should have balance +1 or +2.
  shared_ptr<Node> RotateLeft(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->left) - x->right->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->right;
    shared_ptr<Node> t = z->left;
    if (root == x) root = z;
    x->right = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;

    if (x->parent != nullptr) {
      if (x == x->parent->left)
        x->parent->left = z;
      else
        x->parent->right = z;
    }
    z->left = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if (x->balance == z->balance)
      x->balance = -1;
    else
      x->balance = 0;
    if (old_x_balance == 2)
      z->balance = 0;
    else if (z->balance >= 0)
      z->balance = -1;
    else
      z->balance = -2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
    return z;
  }

  // x and x->left must be non-null. x->right may be null and x->left may be a
  // leaf. x should have balance -1 or -2.
  shared_ptr<Node> RotateRight(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->right) - x->left->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->left;
    shared_ptr<Node> t = z->right;
    if (root == x) root = z;
    x->left = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;
    if (x->parent != nullptr) {
      if (x == x->parent->right)
        x->parent->right = z;
      else
        x->parent->left = z;
    }
    z->right = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if (x->balance == z->balance)
      x->balance = 1;
    else
      x->balance = 0;
    if (old_x_balance == -2)
      z->balance = 0;
    else if (z->balance <= 0)
      z->balance = 1;
    else
      z->balance = 2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
    return z;
  }

  shared_ptr<Node> root;
};

int n;
ll t;
vector<ll> a;

void Load() {
  scanf("%d%lld", &n, &t);
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lld", &a[i]);
  }
}

void Solve() {
  vector<ll> pref(n, 0);
  pref[0] = a[0];
  for (int i = 1; i < n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }

  Multiset multiset;
  multiset.Insert(0);
  ll ans = 0, segment_max = t - 1;
  for (int i = 0; i < n; ++i) {
    ll min_pref_sum = pref[i] - segment_max;
    ans += multiset.CountNumAtLeast(min_pref_sum);
    multiset.Insert(pref[i]);
  }
  printf("%lld\n", ans);
}

int main() {
  Load();
  Solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

struct Node {
  explicit Node(int v, shared_ptr<Node> p) : value(v), parent(p) {}
  int count = 1;
  // Always equal to height(right subtree) - height(left subtree).
  // Can be -2 or +2 during intermediate stages.
  int balance = 0;
  ll value;
  shared_ptr<Node> left;
  shared_ptr<Node> right;
  shared_ptr<Node> parent;
};

// Multiset optimized for querying how many of its elements are at least a
// certain threshold; these queries are O(log n). */
class ThresholdMultiset {
 public:
  ThresholdMultiset() {}

  // O(log n)
  void Insert(ll k) {
    if (root == nullptr) {
      root = make_shared<Node>(k, /*parent=*/nullptr);
      return;
    }

    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    if (cur->value == k) {
      while (cur != nullptr) {
        cur->count++;
        cur = cur->parent;
      }
      return;
    }

    // Add a new node since cur wasn't in the tree.
    const bool increased_height = cur->balance == 0;
    if (k < cur->value) {
      cur->left = make_shared<Node>(k, cur);
      cur->balance--;
    } else {
      cur->right = make_shared<Node>(k, cur);
      cur->balance++;
    }
    cur->count++;

    if (!increased_height) {
      while (cur->parent != nullptr) {
        cur = cur->parent;
        cur->count++;
      }
      return;
    };

    shared_ptr<Node> parent;
    while (cur != nullptr) {
      if (cur->balance == 0) break;
      parent = cur->parent;
      if (parent == nullptr) break;
      parent->count++;
      if (parent->left == cur) {
        parent->balance--;
        if (parent->balance == -2) {
          if (cur->balance == -1) {
            RotateRight(parent);
            break;
          } else {  // cur->balance == 1
            RotateLeft(cur);
            RotateRight(parent);
            cur = cur->parent;
            break;
          }
        }
      } else {
        parent->balance++;
        if (parent->balance == 2) {
          if (cur->balance == 1) {
            RotateLeft(parent);
            break;
          } else {  // cur->balance == -1
            RotateRight(cur);
            RotateLeft(parent);
            cur = cur->parent;
            break;
          }
        }
      }
      cur = parent;
    }

    do {
      cur = cur->parent;
      if (cur == nullptr) break;
      cur->count++;
    } while (cur != nullptr);
  }

  ll CountNumAtLeast(ll t, shared_ptr<Node> n) {
    const int n_left_count = n->left == nullptr ? 0 : n->left->count;
    if (n->value == t) return n->count - n_left_count;
    if (n->value > t) {
      if (n->left == nullptr)
        return n->count;
      else
        return n->count - n_left_count + CountNumAtLeast(t, n->left);
    }
    if (n->right == nullptr) return 0;
    return CountNumAtLeast(t, n->right);
  }

  // O(log n)
  ll CountNumAtLeast(ll t) { return CountNumAtLeast(t, root); }

  // private:
  // Implemented as an AVL tree where each node has a counter for its subtree
  // size. In the Rotate* functions below, x is the root of the old subtree, and
  // they both return the new subtree root.

  // x and x->right must be non-null. x->left may be null and x->right may be a
  // leaf. x should have balance +1 or +2.
  shared_ptr<Node> RotateLeft(shared_ptr<Node> x) {
    const int x_left_count = x->left == nullptr ? 0 : x->left->count;
    const int num_at_x = x->count - x_left_count - x->right->count;

    shared_ptr<Node> z = x->right;
    shared_ptr<Node> t = z->left;
    if (root == x) root = z;
    x->right = t;
    if (t != nullptr) {
      t->parent = x;
    }
    z->parent = x->parent;

    if (x->parent != nullptr) {
      if (x == x->parent->left) {
        x->parent->left = z;
      } else {
        x->parent->right = z;
      }
    }
    z->left = x;
    x->parent = z;

    const int old_x_balance = x->balance;
    if (x->balance == z->balance) {
      x->balance = -1;
    } else {
      x->balance = 0;
    }
    if (old_x_balance == 2) {
      z->balance = 0;
    } else if (z->balance >= 0) {
      z->balance = -1;
    } else {
      z->balance = -2;
    }

    z->count = x->count;
    const int x_right_count = x->right == nullptr ? 0 : x->right->count;
    x->count = x_left_count + x_right_count + num_at_x;
    return z;
  }

  // x and x->left must be non-null. x->right may be null and x->left may be a
  // leaf. x should have balance -1 or -2.
  shared_ptr<Node> RotateRight(shared_ptr<Node> x) {
    const int x_right_count = x->right == nullptr ? 0 : x->right->count;
    const int num_at_x = x->count - x_right_count - x->left->count;

    shared_ptr<Node> z = x->left;
    shared_ptr<Node> t = z->right;
    if (root == x) root = z;
    x->left = t;
    if (t != nullptr) {
      t->parent = x;
    }
    z->parent = x->parent;
    if (x->parent != nullptr) {
      if (x == x->parent->right) {
        x->parent->right = z;
      } else {
        x->parent->left = z;
      }
    }
    z->right = x;
    x->parent = z;

    const int old_x_balance = x->balance;
    if (x->balance == z->balance) {
      x->balance = 1;
    } else {
      x->balance = 0;
    }
    if (old_x_balance == -2) {
      z->balance = 0;
    } else if (z->balance <= 0) {
      z->balance = 1;
    } else {
      z->balance = 2;
    }

    z->count = x->count;
    const int x_left_count = x->left == nullptr ? 0 : x->left->count;
    x->count = x_right_count + x_left_count + num_at_x;
    return z;
  }

  shared_ptr<Node> root;
};

int n;
ll t;
vector<ll> a;

void Load() {
  scanf("%d%lld", &n, &t);
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lld", &a[i]);
  }
}

void Solve() {
  vector<ll> pref(n, 0);
  pref[0] = a[0];
  for (int i = 1; i < n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }

  ThresholdMultiset multiset;
  multiset.Insert(0);
  ll ans = 0, segment_max = t - 1;
  for (int i = 0; i < n; ++i) {
    ll min_pref_sum = pref[i] - segment_max;
    ans += multiset.CountNumAtLeast(min_pref_sum);
    multiset.Insert(pref[i]);
  }
  printf("%lld\n", ans);
}

bool CheckNode(shared_ptr<Node> n, int val, int cnt, int bal) {
  bool res = n->count == cnt && n->balance == bal && n->value == val;
  if (!res) {
    printf(
        "Failed! (Expected, Actual) Values %d %d Counts %d %d Balances %d %d\n",
        val, n->value, cnt, n->count, bal, n->balance);
  }
  return res;
}

/* TESTS */

bool IsLeaf(shared_ptr<Node> n) {
  return n->left == nullptr && n->right == nullptr;
}

bool Test5() {
  ThresholdMultiset m;
  m.Insert(5);
  shared_ptr<Node>& r = m.root;
  if (!CheckNode(r, 5, 1, 0)) return false;
  if (!IsLeaf(r) || r->parent != nullptr) {
    return false;
  }
  return true;
}

bool Test53() {
  ThresholdMultiset m;
  m.Insert(5);
  m.Insert(3);
  auto& r = m.root;
  auto& l = r->left;
  if (!CheckNode(r, 5, 2, -1)) return false;
  if (!CheckNode(r->left, 3, 1, 0)) return false;
  if (r->right != nullptr || r->parent != nullptr || !IsLeaf(l)) {
    return false;
  }
  if (l->parent != r) {
    return false;
  }
  return true;
}

bool Test35() {
  ThresholdMultiset m;
  m.Insert(3);
  m.Insert(5);
  auto& r = m.root;
  auto& rht = r->right;
  if (!CheckNode(r, 3, 2, 1)) return false;
  if (!CheckNode(r->right, 5, 1, 0)) return false;
  if (r->left != nullptr || r->parent != nullptr || !IsLeaf(rht)) {
    return false;
  }
  if (rht->parent != r) {
    return false;
  }
  return true;
}

bool Test55() {
  ThresholdMultiset m;
  m.Insert(5);
  m.Insert(5);
  auto& r = m.root;
  if (!CheckNode(r, 5, 2, 0)) return false;
  if (r->parent != nullptr || !IsLeaf(r)) {
    return false;
  }
  return true;
}

bool Test435() {
  ThresholdMultiset m;
  m.Insert(4);
  m.Insert(3);
  m.Insert(5);
  auto& r = m.root;
  if (!CheckNode(r, 4, 3, 0)) return false;
  auto& rht = r->right;
  auto& lft = r->left;
  if (!CheckNode(rht, 5, 1, 0)) return false;
  if (!CheckNode(lft, 3, 1, 0)) return false;
  if (r->parent != nullptr || !IsLeaf(rht) || !IsLeaf(lft)) return false;
  return true;
}

bool Test3251() {
  ThresholdMultiset m;
  m.Insert(3);
  m.Insert(2);
  m.Insert(5);
  m.Insert(1);
  auto& r = m.root;
  auto& n2 = r->left;
  auto& n5 = r->right;
  auto& n1 = n2->left;
  if (!CheckNode(r, 3, 4, -1)) return false;
  if (!CheckNode(n2, 2, 2, -1)) return false;
  if (!CheckNode(n5, 5, 1, 0)) return false;
  if (!CheckNode(n1, 1, 1, 0)) return false;
  if (r->parent != nullptr || n2->right != nullptr || !IsLeaf(n1) ||
      !IsLeaf(n5))
    return false;
  return true;
}

bool Test325121() {
  ThresholdMultiset m;
  m.Insert(3);
  m.Insert(2);
  m.Insert(5);
  m.Insert(1);
  m.Insert(2);
  m.Insert(1);
  auto& r = m.root;
  if (!CheckNode(r, 3, 6, -1)) return false;
  auto& n2 = r->left;
  auto& n5 = r->right;
  auto& n1 = n2->left;
  if (!CheckNode(n2, 2, 4, -1)) return false;
  if (!CheckNode(n5, 5, 1, 0)) return false;
  if (!CheckNode(n1, 1, 2, 0)) return false;
  if (r->parent != nullptr || n2->right != nullptr || !IsLeaf(n1) ||
      !IsLeaf(n5))
    return false;
  return true;
}

bool Test4261357() {
  ThresholdMultiset m;
  m.Insert(4);
  m.Insert(2);
  m.Insert(6);
  m.Insert(1);
  m.Insert(3);
  m.Insert(5);
  m.Insert(7);
  auto& r = m.root;
  auto& n2 = r->left;
  auto& n6 = r->right;
  auto& n1 = n2->left;
  auto& n3 = n2->right;
  auto& n5 = n6->left;
  auto& n7 = n6->right;
  if (!CheckNode(r, 4, 7, 0)) return false;
  if (!CheckNode(n2, 2, 3, 0)) return false;
  if (!CheckNode(n6, 6, 3, 0)) return false;
  if (!CheckNode(n1, 1, 1, 0)) return false;
  if (!CheckNode(n3, 3, 1, 0)) return false;
  if (!CheckNode(n5, 5, 1, 0)) return false;
  if (!CheckNode(n7, 7, 1, 0)) return false;
  if (r->parent != nullptr || !IsLeaf(n1) || !IsLeaf(n3) || !IsLeaf(n5) ||
      !IsLeaf(n7))
    return false;
  return true;
}

bool Test543() {
  ThresholdMultiset m;
  m.Insert(5);
  m.Insert(4);
  m.Insert(3);
  auto& r = m.root;
  auto& lft = r->left;
  auto& rht = r->right;
  if (!CheckNode(r, 4, 3, 0)) return false;
  if (!CheckNode(lft, 3, 1, 0)) return false;
  if (!CheckNode(rht, 5, 1, 0)) return false;
  if (!IsLeaf(lft) || !IsLeaf(rht)) return false;
  return true;
}

bool Test345() {
  ThresholdMultiset m;
  m.Insert(3);
  m.Insert(4);
  m.Insert(5);
  auto& r = m.root;
  if (!CheckNode(r, 4, 3, 0)) return false;
  auto& lft = r->left;
  auto& rht = r->right;
  if (!CheckNode(lft, 3, 1, 0)) return false;
  if (!CheckNode(rht, 5, 1, 0)) return false;
  if (!IsLeaf(lft) || !IsLeaf(rht)) return false;
  return true;
}

bool Test354() {
  ThresholdMultiset m;
  m.Insert(3);
  m.Insert(5);
  m.Insert(4);
  auto& r = m.root;
  auto& lft = r->left;
  auto& rht = r->right;
  if (!CheckNode(r, 4, 3, 0)) return false;
  if (!CheckNode(lft, 3, 1, 0)) return false;
  if (!CheckNode(rht, 5, 1, 0)) return false;
  if (!IsLeaf(lft) || !IsLeaf(rht)) return false;
  return true;
}

bool Test534() {
  ThresholdMultiset m;
  m.Insert(5);
  m.Insert(3);
  m.Insert(4);
  auto& r = m.root;
  auto& lft = r->left;
  auto& rht = r->right;
  if (!CheckNode(r, 4, 3, 0)) return false;
  if (!CheckNode(lft, 3, 1, 0)) return false;
  if (!CheckNode(rht, 5, 1, 0)) return false;
  if (!IsLeaf(lft) || !IsLeaf(rht)) return false;
  return true;
}

bool Test526413() {
  ThresholdMultiset m;
  m.Insert(5);
  m.Insert(2);
  m.Insert(6);
  m.Insert(4);
  m.Insert(1);
  m.Insert(3);
  auto& r = m.root;
  auto& n2 = r->left;
  auto& n5 = r->right;
  auto& n1 = n2->left;
  auto& n3 = n2->right;
  auto& n6 = n5->right;
  if (!CheckNode(r, 4, 6, 0)) return false;
  if (!CheckNode(n2, 2, 3, 0)) return false;
  if (!CheckNode(n5, 5, 2, 1)) return false;
  if (!CheckNode(n1, 1, 1, 0)) return false;
  if (!CheckNode(n3, 3, 1, 0)) return false;
  if (!CheckNode(n6, 6, 1, 0)) return false;
  if (r->parent != nullptr || n5->left != nullptr || !IsLeaf(n1) ||
      !IsLeaf(n3) || !IsLeaf(n6))
    return false;
  for (int i = 1; i < 8; ++i) {
    if (m.CountNumAtLeast(i) != 7 - i) return false;
  }
  if (m.CountNumAtLeast(-3) != 6) return false;
  return true;
}

bool Test344() {
  ThresholdMultiset m;
  m.Insert(3);
  m.Insert(4);
  m.Insert(4);
  auto& r = m.root;
  auto& rht = r->right;
  if (!CheckNode(r, 3, 3, 1)) return false;
  if (!CheckNode(rht, 4, 2, 0)) return false;
  if (r->parent != nullptr || !IsLeaf(rht)) return false;
  return true;
}

bool Test627145() {
  ThresholdMultiset m;
  m.Insert(6);
  m.Insert(2);
  m.Insert(7);
  m.Insert(1);
  m.Insert(4);
  m.Insert(5);
  auto& r = m.root;
  auto& n2 = r->left;
  auto& n6 = r->right;
  auto& n1 = n2->left;
  auto& n5 = n6->left;
  auto& n7 = n6->right;
  if (!CheckNode(r, 4, 6, 0)) return false;
  if (!CheckNode(n2, 2, 2, -1)) return false;
  if (!CheckNode(n6, 6, 3, 0)) return false;
  if (!CheckNode(n1, 1, 1, 0)) return false;
  if (!CheckNode(n5, 5, 1, 0)) return false;
  if (!CheckNode(n7, 7, 1, 0)) return false;
  if (r->parent != nullptr || n2->right != nullptr || !IsLeaf(n1) ||
      !IsLeaf(n5) || !IsLeaf(n7))
    return false;
  return true;
}

bool Test44665() {
  ThresholdMultiset m;
  m.Insert(4);
  m.Insert(4);
  m.Insert(6);
  m.Insert(6);
  m.Insert(5);
  auto& r = m.root;
  auto& lft = r->left;
  auto& rht = r->right;
  if (!CheckNode(r, 5, 5, 0)) return false;
  if (!CheckNode(lft, 4, 2, 0)) return false;
  if (!CheckNode(rht, 6, 2, 0)) return false;
  if (r->parent != nullptr || !IsLeaf(lft) || !IsLeaf(rht)) return false;
  return true;
}

bool Test123456() {
  ThresholdMultiset m;
  for (int i = 1; i < 7; ++i) m.Insert(i);
  auto& r = m.root;
  auto& n2 = r->left;
  auto& n5 = r->right;
  auto& n1 = n2->left;
  auto& n3 = n2->right;
  auto& n6 = n5->right;
  if (!CheckNode(r, 4, 6, 0)) return false;
  if (!CheckNode(n2, 2, 3, 0)) return false;
  if (!CheckNode(n5, 5, 2, 1)) return false;
  if (!CheckNode(n1, 1, 1, 0)) return false;
  if (!CheckNode(n3, 3, 1, 0)) return false;
  if (!CheckNode(n6, 6, 1, 0)) return false;
  if (r->parent != nullptr || n5->left != nullptr || !IsLeaf(n1) ||
      !IsLeaf(n3) || !IsLeaf(n6))
    return false;
  return true;
}

bool TestMega1() {
  ThresholdMultiset m;
  auto& r = m.root;
  m.Insert(4);
  m.Insert(2);
  m.Insert(7);
  m.Insert(1);
  m.Insert(5);
  m.Insert(3);
  m.Insert(10);
  m.Insert(6);
  m.Insert(8);
  m.Insert(12);
  if (r->right->value != 7) return false;
  if (!CheckNode(r, 4, 10, 1)) return false;

  m.Insert(7);
  if (!CheckNode(r, 4, 11, 1)) return false;
  m.Insert(7);
  m.Insert(5);
  m.Insert(4);
  m.Insert(9);

  if (!CheckNode(r, 7, 15, 0)) return false;
  auto& n5 = r->left->right;
  if (!CheckNode(n5, 5, 3, 1)) return false;
  auto& n4 = r->left;
  if (!CheckNode(n4, 4, 8, 0)) return false;
  auto& n9 = r->right->left->right;
  if (!CheckNode(n9, 9, 1, 0)) return false;
  auto& n10 = r->right;
  if (!CheckNode(n10, 10, 4, -1)) return false;
  if (m.CountNumAtLeast(3) != 13) return false;
  if (m.CountNumAtLeast(7) != 7) return false;
  if (m.CountNumAtLeast(13) != 0) return false;
  if (n10->left->left != nullptr || !IsLeaf(n9) || !IsLeaf(n10->right) ||
      n5->left != nullptr)
    return false;
  return true;
}

void Test() {
  puts(Test5() ? "1 PASS" : "FAIL");
  puts(Test53() ? "2 PASS" : "FAIL");
  puts(Test35() ? "3 PASS" : "FAIL");
  puts(Test55() ? "4 PASS" : "FAIL");
  puts(Test435() ? "5 PASS" : "FAIL");
  puts(Test3251() ? "6 PASS" : "FAIL");
  puts(Test325121() ? "7 PASS" : "FAIL");
  puts(Test4261357() ? "8 PASS" : " FAIL");
  puts(Test543() ? "9 PASS" : "FAIL");
  puts(Test345() ? "10 PASS" : "FAIL");
  puts(Test354() ? "11 PASS" : "FAIL");
  puts(Test534() ? "12 PASS" : "FAIL");
  puts(Test526413() ? "13 PASS" : "FAIL");
  puts(Test344() ? "14 PASS" : "FAIL");
  puts(Test627145() ? "15 PASS" : "FAIL");
  puts(Test44665() ? "16 PASS" : "FAIL");
  puts(Test123456() ? "17 PASS" : "FAIL");
  puts(TestMega1() ? "18 PASS" : " FAIL");
}

int main() {
  // Test();
  Load();
  Solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

/* BEGIN LIBRARIES */

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

/* BEGIN LIBRARIES */

// Multiset with Log(N) queries for getting element at k-th rank, and finding
// the number of elements that are at least a given threshold.
class Multiset {
  // Implemented as an AVL tree where each node keeps track of its subtree size.
 public:
  Multiset() {}

  void Insert(ll k) {
    if (root == nullptr) {
      root = make_shared<Node>(k, /*parent=*/nullptr);
      return;
    }

    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    // Found k. No need to update balances or do rotations.
    if (cur->value == k) {
      while (cur != nullptr) {
        cur->subtree_size++;
        cur = cur->parent;
      }
      return;
    }

    // Add a new node since cur wasn't in the tree.
    const bool increased_height = cur->balance == 0;
    if (k < cur->value) {
      cur->left = make_shared<Node>(k, cur);
      cur->balance--;
    } else {
      cur->right = make_shared<Node>(k, cur);
      cur->balance++;
    }
    cur->subtree_size++;

    // No need to do rotations if the new node did not increase the height of
    // its parent.
    if (!increased_height) {
      while (cur->parent != nullptr) {
        cur = cur->parent;
        cur->subtree_size++;
      }
      return;
    };

    shared_ptr<Node> parent;
    // Walk from the inserted node to the root, doing a rotation if necessary.
    // If an iteration of the while loop performs a rotation (or two), we can
    // break since no nodes further up the tree will need a rotation.
    while (cur != nullptr) {
      if (cur->balance == 0) break;
      parent = cur->parent;
      if (parent == nullptr) break;
      parent->subtree_size++;
      if (parent->left == cur) {
        parent->balance--;
        if (parent->balance == -2) {
          if (cur->balance == -1) {
            RotateRight(parent);
            break;
          } else {  // cur->balance == 1
            RotateLeft(cur);
            RotateRight(parent);
            cur = cur->parent;
            break;
          }
        }
      } else {
        parent->balance++;
        if (parent->balance == 2) {
          if (cur->balance == 1) {
            RotateLeft(parent);
            break;
          } else {  // cur->balance == -1
            RotateRight(cur);
            RotateLeft(parent);
            cur = cur->parent;
            break;
          }
        }
      }
      cur = parent;
    }

    do {
      cur = cur->parent;
      if (cur == nullptr) break;
      cur->subtree_size++;
    } while (cur != nullptr);
  }

  // Removes one instance of k from the Multiset. Does nothing if t is not
  // present. O(log N)
  void Delete(ll k) {
    if (root == nullptr) return;
    shared_ptr<Node> cur = root;
    // Find where 'k' should be in the tree.
    while (cur->value != k &&
           (k < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = k < cur->value ? cur->left : cur->right;
    }
    if (cur->value != k) return;  // k was not present.
    if (cur->subtree_size >
        1 + SubtreeSize(cur->left) + SubtreeSize(cur->right)) {
      // No nodes need to be removed.
      while (cur != nullptr) {
        cur->subtree_size--;
        cur = cur->parent;
      }
      return;
    }

    // Invariants: One of rebalance_node's children has had one of its child
    // subtrees' heights lowered by one. (However, rebalance_node may be
    // nullptr, in which case there will be nothing left to update.
    // left_subtree_shrunk boolean helps keep track of which one it is.
    shared_ptr<Node> rebalance_node;
    bool left_subtree_shrunk;
    // Delete the node. subtree_size's and balances in the tree at cur or above
    // may become outdated.
    if (cur->left == nullptr && cur->right == nullptr) {
      // Case 1: cur has no children.
      if (cur->parent != nullptr) {
        rebalance_node = cur->parent;
        left_subtree_shrunk = cur->parent->left == cur;
      }
      DeleteChildlessNode(cur);
    } else if (cur->left == nullptr || cur->right == nullptr) {
      // Case 2: cur has exactly one child.
      if (cur->parent != nullptr) {
        rebalance_node = cur->parent;
        left_subtree_shrunk = cur->parent->left == cur;
      }
      MoveChildInto(cur);
    } else {
      // Case 3: cur has two children.
      left_subtree_shrunk = cur->right->left != nullptr;
      rebalance_node = MoveInorderSuccessorInto(cur);
    }

    // Then, for all three cases above, start at the smallest subtree with its
    // height decreased by one. Trace up the tree, while updating all data
    // structures and making sure all balances are within [-1, 1].
    // Invariant: Upon loop start, rebalance_node's balance and subtree_size are
    // outdated, but all balances and subtree_size's under it are correct.
    while (rebalance_node != nullptr) {
      rebalance_node->subtree_size--;
      // Save parent because some rotations might happen.
      shared_ptr<Node> parent = rebalance_node->parent;
      bool new_left_subtree_shrunk;
      if (parent != nullptr)
        new_left_subtree_shrunk = parent->left == rebalance_node;
      if (left_subtree_shrunk) {
        rebalance_node->balance++;  // This balance is now in [0, 2].
        if (rebalance_node->balance == 2) {
          shared_ptr<Node> child = rebalance_node->right;
          if (child->balance < 0) {
            RotateRight(child);
            RotateLeft(rebalance_node);
          } else {
            RotateLeft(rebalance_node);
          }
        } else if (rebalance_node->balance == 1) {
          rebalance_node->balance = 1;
          rebalance_node = rebalance_node->parent;
          while (rebalance_node != nullptr) {
            rebalance_node->subtree_size--;
            rebalance_node = rebalance_node->parent;
          }
          break;
        } else {  // rebalance_node->balance == 0
          rebalance_node->balance = 0;
        }
      } else {                      // right subtree shrunk
        rebalance_node->balance--;  // This balance is now in [-2, 0].
        if (rebalance_node->balance == -2) {
          shared_ptr<Node> child = rebalance_node->left;
          if (child->balance > 0) {
            RotateLeft(child);
            RotateRight(rebalance_node);
          } else {
            RotateRight(rebalance_node);
          }
        } else if (rebalance_node->balance == -1) {
          rebalance_node->balance = -1;
          rebalance_node = rebalance_node->parent;
          while (rebalance_node != nullptr) {
            rebalance_node->subtree_size--;
            rebalance_node = rebalance_node->parent;
          }
          break;
        } else {  // rebalance_node->balance == 0
          rebalance_node->balance = 0;
        }
      }
      rebalance_node = parent;
      left_subtree_shrunk = new_left_subtree_shrunk;
    }
  }

  // O(log N)
  ll CountNumAtLeast(ll t) { return CountNumAtLeast(t, root); }
  ll Size() { return SubtreeSize(root); }
  ll Count(ll t) { return Count(t, root); }

 private:
  struct Node {
    explicit Node(ll v, shared_ptr<Node> p) : value(v), parent(p) {}
    int subtree_size = 1;
    // Equals height(right subtree) - height(left subtree).
    // Can be -2 or +2 during intermediate stages.
    int balance = 0;
    ll value;
    shared_ptr<Node> left;
    shared_ptr<Node> right;
    shared_ptr<Node> parent;
  };

  // Convenience function for getting the subtree_size of a possibly null Node.
  ll SubtreeSize(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return n->subtree_size;
  }

  ll CountNumAtLeast(ll t, shared_ptr<Node> n) {
    const int n_left_subtree_size = SubtreeSize(n->left);
    if (n->value == t) return n->subtree_size - n_left_subtree_size;
    if (n->value > t) {
      if (n->left == nullptr)
        return n->subtree_size;
      else
        return n->subtree_size - n_left_subtree_size +
               CountNumAtLeast(t, n->left);
    }
    if (n->right == nullptr) return 0;
    return CountNumAtLeast(t, n->right);
  }

  // n may be nullptr
  ll Count(ll t, shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    if (n->value == t)
      return SubtreeSize(n) - SubtreeSize(n->left) - SubtreeSize(n->right);
    if (n->value > t)
      return Count(t, n->left);
    else
      return Count(t, n->right);
  }

  ll Count(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return SubtreeSize(n) - SubtreeSize(n->left) - SubtreeSize(n->right);
  }

  // Does not update balances or subtree_size's above x.
  void DeleteChildlessNode(shared_ptr<Node> x) {
    if (x == root) {
      root = nullptr;
      return;
    }
    shared_ptr<Node> parent = x->parent;  // cannot be nullptr
    if (parent->left == x)
      parent->left = nullptr;
    else
      parent->right = nullptr;
  }

  // Preconditions: n has exactly child. Note that x's child must be childless.
  // Does not update: 1) balances at x or above, 2) subtree_size's above x.
  void MoveChildInto(shared_ptr<Node> x) {
    if (x == root) {
      if (x->left != nullptr) {
        x->left->parent = nullptr;
        root = x->left;
      } else {
        x->right->parent = nullptr;
        root = x->right;
      }
      return;
    }
    shared_ptr<Node> child = x->left == nullptr ? x->right : x->left;
    x->value = child->value;
    x->subtree_size = child->subtree_size;
    if (child == x->left)
      x->left = nullptr;
    else
      x->right = nullptr;
  }

  // Does not update: 1) balances at inorder successor or above, 2)
  // subtree_size's above x.
  // At the end of this function,the returned Node and all ancestor Nodes
  // will have a subtree_size that is exactly one more than it should be.
  // Returns the parent of the inorder successor's Node (before moving it).
  shared_ptr<Node> MoveInorderSuccessorInto(shared_ptr<Node> x) {
    shared_ptr<Node> successor = x->right;
    while (successor->left != nullptr) successor = successor->left;
    shared_ptr<Node> successor_original_parent = successor->parent;

    int old_successor_count = Count(successor);  // 0 or 1
    // Copy the successor data into x.
    x->value = successor->value;
    x->subtree_size =
        old_successor_count + x->left->subtree_size + x->right->subtree_size;
    // Update the subtree sizes of all nodes in between the current and old
    // successor nodes (to account for the swap.)
    shared_ptr<Node> nodes_from_successor_to_x = successor->parent;
    while (nodes_from_successor_to_x != x) {
      nodes_from_successor_to_x->subtree_size -= (old_successor_count - 1);
      nodes_from_successor_to_x = nodes_from_successor_to_x->parent;
    }

    // Delete old the successor node.
    if (successor->right == nullptr)
      DeleteChildlessNode(successor);  // successor cannot have a left child
    else
      MoveChildInto(successor);

    return successor_original_parent;
  }

  // In the Rotate* functions below, x is the root of the old subtree.
  // Preconditions: balances and counts at x and under must be accurate.
  // Postconditions: balances and counts at x and under will be accurate.
  //
  // x and x->right must be non-null. x->left may be null and x->right may be a
  // leaf. x should have balance +1 or +2.
  void RotateLeft(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->left) - x->right->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->right;
    shared_ptr<Node> t = z->left;
    if (root == x) root = z;
    x->right = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;

    if (x->parent != nullptr) {
      if (x == x->parent->left)
        x->parent->left = z;
      else
        x->parent->right = z;
    }
    z->left = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if ((x->balance == = 1 && z->balance == 1) ||
        (x->balance == 2 && z->balance == 2))
      x->balance = -1;
    else
      x->balance = 0;
    if (old_x_balance == 2)
      z->balance = 0;
    else if (z->balance >= 0)
      z->balance = -1;
    else
      z->balance = -2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
  }

  // x and x->left must be non-null. x->right may be null and x->left may be a
  // leaf. x should have balance -1 or -2.
  void RotateRight(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->right) - x->left->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->left;
    shared_ptr<Node> t = z->right;
    if (root == x) root = z;
    x->left = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;
    if (x->parent != nullptr) {
      if (x == x->parent->right)
        x->parent->right = z;
      else
        x->parent->left = z;
    }
    z->right = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if ((x->balance == -1 && z->balance == -1) ||
        (x->balance == 2 && z->balance == 2))
      x->balance = 1;
    else {
      if (x->balance == z->balance) printf("XBAL EQ %d\n", x->balance);
      // ERROR this is incorrect now.
      x->balance = 0;
    }
    if (old_x_balance == -2)
      z->balance = 0;
    else if (z->balance <= 0)
      z->balance = 1;
    else
      z->balance = 2;

    z->subtree_size = x->subtree_size;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
  }

  shared_ptr<Node> root;
};
/* END LIBRARIES */

int n;
ll t;
vector<ll> a;

void Load() {
  scanf("%d%lld", &n, &t);
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lld", &a[i]);
  }
}

void Solve() {
  vector<ll> pref(n, 0);
  pref[0] = a[0];
  for (int i = 1; i < n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }

  Multiset multiset;
  multiset.Insert(0);
  ll ans = 0, segment_max = t - 1;
  for (int i = 0; i < n; ++i) {
    ll min_pref_sum = pref[i] - segment_max;
    ans += multiset.CountNumAtLeast(min_pref_sum);
    multiset.Insert(pref[i]);
  }
  printf("%lld\n", ans);
}

int main() {
  Load();
  Solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

/* BEGIN LIBRARIES */

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

/* BEGIN LIBRARIES */

// Multiset with Log(N) queries for getting element at k-th rank, and finding
// the number of elements that are at least a given threshold.
class Multiset {
 public:
  // Implemented as a modified AVL tree.
  Multiset() {}

  // Insert n instances of val into the multiset.
  void InsertNTimes(ll val, ll n) {
    if (root == nullptr) {
      root = make_shared<Node>(val, n, /*parent=*/nullptr);
      return;
    }

    shared_ptr<Node> cur = root;
    // Find where val should be in the tree.
    while (cur->value != val &&
           (val < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = val < cur->value ? cur->left : cur->right;
    }
    // Found val. No need to update balances or do rotations.
    if (cur->value == val) {
      while (cur != nullptr) {
        AddToSubtreeNTimes(cur, val, n);
        cur = cur->parent;
      }
      return;
    }

    // Add a new node since cur wasn't in the tree.
    const bool increased_height = cur->balance == 0;
    if (val < cur->value) {
      cur->left = make_shared<Node>(val, n, cur);
      cur->balance--;
    } else {
      cur->right = make_shared<Node>(val, n, cur);
      cur->balance++;
    }
    AddToSubtreeNTimes(cur, val, n);

    // No need to do rotations if the new node did not increase the height of
    // its parent.
    if (!increased_height) {
      while (cur->parent != nullptr) {
        cur = cur->parent;
        AddToSubtreeNTimes(cur, val, n);
      }
      return;
    };

    shared_ptr<Node> parent;
    // Walk from the parent of the inserted node to the root, doing a rotation
    // if necessary. If an iteration of the while loop performs a rotation (or
    // two), we can break since no nodes further up the tree will need a
    // rotation.
    while (cur != nullptr) {
      if (cur->balance == 0) break;
      parent = cur->parent;
      if (parent == nullptr) break;
      AddToSubtreeNTimes(parent, val, n);
      if (parent->left == cur) {
        parent->balance--;
        if (parent->balance == -2) {
          if (cur->balance == -1) {
            RotateRight(parent);
            break;
          } else {  // cur->balance == 1
            RotateLeft(cur);
            RotateRight(parent);
            cur = cur->parent;
            break;
          }
        }
      } else {
        parent->balance++;
        if (parent->balance == 2) {
          if (cur->balance == 1) {
            RotateLeft(parent);
            break;
          } else {  // cur->balance == -1
            RotateRight(cur);
            RotateLeft(parent);
            cur = cur->parent;
            break;
          }
        }
      }
      cur = parent;
    }

    do {
      cur = cur->parent;
      if (cur == nullptr) break;
      AddToSubtreeNTimes(cur, val, n);
    } while (cur != nullptr);
  }

  void Insert(ll k) { InsertNTimes(k, 1); }

  // Removes n instances of val from the multiset. If n > Count(val) the
  // multiset will just end up with Count(val) == 0.  O(log N)
  void DeleteNTimes(ll val, ll n) {
    if (root == nullptr) return;
    shared_ptr<Node> cur = root;
    // Find where val should be in the tree.
    while (cur->value != val &&
           (val < cur->value ? cur->left != nullptr : cur->right != nullptr)) {
      cur = val < cur->value ? cur->left : cur->right;
    }
    if (cur->value != val) return;  // val was not present.
    if (Count(cur) > n) {
      // No nodes need to be removed.
      while (cur != nullptr) {
        AddToSubtreeNTimes(cur, val, -n);
        cur = cur->parent;
      }
      return;
    }
    n = min(Count(cur), n);

    // Invariants: One of rebalance_node's children has had one of its child
    // subtrees' heights lowered by one. (However, rebalance_node may be
    // nullptr, in which case there will be nothing left to update.
    // left_subtree_shrunk boolean helps keep track of which one it is.
    shared_ptr<Node> rebalance_node;
    bool left_subtree_shrunk;
    // Delete the node. subtree_size's and balances in the tree at cur or above
    // may become outdated.
    if (cur->left == nullptr && cur->right == nullptr) {
      // Case 1: cur has no children.
      if (cur->parent != nullptr) {
        rebalance_node = cur->parent;
        left_subtree_shrunk = cur->parent->left == cur;
      }
      DeleteChildlessNode(cur);
    } else if (cur->left == nullptr || cur->right == nullptr) {
      // Case 2: cur has exactly one child.
      if (cur->parent != nullptr) {
        rebalance_node = cur->parent;
        left_subtree_shrunk = cur->parent->left == cur;
      }
      MoveChildInto(cur);
    } else {
      // Case 3: cur has two children.
      left_subtree_shrunk = cur->right->left != nullptr;
      rebalance_node = MoveInorderSuccessorInto(cur);
    }

    // Then, for all three cases above, start at the smallest subtree with its
    // height decreased by one. Trace up the tree, while updating all data
    // structures and making sure all balances are within [-1, 1].
    // Invariant: Upon loop start, rebalance_node's balance and subtree_size are
    // outdated, but all balances and subtree_size's under it are correct.
    while (rebalance_node != nullptr) {
      AddToSubtreeNTimes(rebalance_node, val, -n);
      // Save parent because some rotations might happen.
      shared_ptr<Node> parent = rebalance_node->parent;
      bool new_left_subtree_shrunk;
      if (parent != nullptr)
        new_left_subtree_shrunk = parent->left == rebalance_node;
      if (left_subtree_shrunk) {
        rebalance_node->balance++;  // This balance is now in [0, 2].
        if (rebalance_node->balance == 2) {
          shared_ptr<Node> child = rebalance_node->right;
          if (child->balance < 0) {
            RotateRight(child);
            RotateLeft(rebalance_node);
          } else if (child->balance == 0) {
            RotateLeft(rebalance_node);
            while (parent != nullptr) {
              rebalance_node = parent;
              AddToSubtreeNTimes(rebalance_node, val, -n);
              parent = rebalance_node->parent;
            }
            break;
          } else if (child->balance == 1) {
            RotateLeft(rebalance_node);
          }
        } else if (rebalance_node->balance == 1) {
          rebalance_node->balance = 1;
          while (parent != nullptr) {
            rebalance_node = parent;
            AddToSubtreeNTimes(rebalance_node, val, -n);
            parent = rebalance_node->parent;
          }
          break;
        } else {  // rebalance_node->balance == 0
          rebalance_node->balance = 0;
        }
      } else {                      // right subtree shrunk
        rebalance_node->balance--;  // This balance is now in [-2, 0].
        if (rebalance_node->balance == -2) {
          shared_ptr<Node> child = rebalance_node->left;
          if (child->balance > 0) {
            RotateLeft(child);
            RotateRight(rebalance_node);
          } else if (child->balance == 0) {
            RotateRight(rebalance_node);
            while (parent != nullptr) {
              rebalance_node = parent;
              AddToSubtreeNTimes(rebalance_node, val, -n);
              parent = rebalance_node->parent;
            }
            break;
          } else if (child->balance == -1) {
            RotateRight(rebalance_node);
          }
        } else if (rebalance_node->balance == -1) {
          rebalance_node->balance = -1;
          while (parent != nullptr) {
            rebalance_node = parent;
            AddToSubtreeNTimes(rebalance_node, val, -n);
            parent = rebalance_node->parent;
          }
          break;
        } else {  // rebalance_node->balance == 0
          rebalance_node->balance = 0;
        }
      }
      rebalance_node = parent;
      left_subtree_shrunk = new_left_subtree_shrunk;
    }
  }

  void Delete(ll k) { DeleteNTimes(k, 1); }

  // O(log N)
  ll CountNumAtLeast(ll t) { return CountNumAtLeast(t, root); }
  // O(log N).  Will return -1 if k is greater than tree size.
  ll AtRank(ll k) {
    if (k > Size()) return -1;
    return AtRank(k, root);
  }
  ll Size() { return SubtreeSize(root); }
  ll Count(ll t) { return Count(t, root); }
  // Returns sum of the greatest or least M elements, where M = min(k, Size()).
  ll SumOfGreatest(ll k) {
    if (k <= 0 || root == nullptr) return 0;
    return SumOfGreatest(min(k, Size()), root);
  }
  ll SumOfLeast(ll k) { return SubtreeSum(root) - SumOfGreatest(Size() - k); }

 private:
  struct Node {
    Node(ll v, ll cardinality, shared_ptr<Node> p)
        : value(v),
          subtree_size(cardinality),
          subtree_sum(v * cardinality),
          parent(p) {}
    int subtree_size;
    ll subtree_sum;
    // Equals height(right subtree) - height(left subtree).
    // Can be -2 or +2 during intermediate stages.
    int balance = 0;
    ll value;
    shared_ptr<Node> left;
    shared_ptr<Node> right;
    shared_ptr<Node> parent;
  };

  // NULL-HANDLING ACCESSOR FUNCTIONS ==========================================
  ll SubtreeSize(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return n->subtree_size;
  }
  ll Count(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return SubtreeSize(n) - SubtreeSize(n->left) - SubtreeSize(n->right);
  }
  ll SubtreeSum(shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    return n->subtree_sum;
  }

  // REFACTORED ================================================================
  // To remove from subtree N times, just make num_times negative.
  void AddToSubtreeNTimes(shared_ptr<Node> node, ll value, ll num_times) {
    node->subtree_size += num_times;
    node->subtree_sum += num_times * value;
  }

  // API HELPER FUNCTIONS ======================================================
  // n should be non-null
  ll CountNumAtLeast(ll t, shared_ptr<Node> n) {
    const int n_left_subtree_size = SubtreeSize(n->left);
    if (n->value == t) return n->subtree_size - n_left_subtree_size;
    if (n->value > t) {
      if (n->left == nullptr)
        return n->subtree_size;
      else
        return n->subtree_size - n_left_subtree_size +
               CountNumAtLeast(t, n->left);
    }
    return CountNumAtLeast(t, n->right);
  }

  // n should be non-null
  ll AtRank(ll k, shared_ptr<Node> n) {
    if (SubtreeSize(n->right) >= k) return AtRank(k, n->right);
    if (SubtreeSize(n->right) + Count(n) >= k) return n->value;
    return AtRank(k - SubtreeSize(n->right) - Count(n), n->left);
  }

  // n should be non-null
  ll SumOfGreatest(ll k, shared_ptr<Node> n) {
    if (SubtreeSize(n->right) >= k) return SumOfGreatest(k, n->right);
    if (SubtreeSize(n->right) + Count(n) >= k) {
      return SubtreeSum(n->right) + (k - SubtreeSize(n->right)) * n->value;
    }
    return SubtreeSum(n->right) + Count(n) * n->value +
           SumOfGreatest(k - SubtreeSize(n->right) - Count(n), n->left);
  }

  // n may be nullptr
  ll Count(ll t, shared_ptr<Node> n) {
    if (n == nullptr) return 0;
    if (n->value == t)
      return SubtreeSize(n) - SubtreeSize(n->left) - SubtreeSize(n->right);
    if (n->value > t)
      return Count(t, n->left);
    else
      return Count(t, n->right);
  }

  // DELETION IMPLEMENTATION  ==================================================
  // Does not update balances or subtree_size's above x.
  void DeleteChildlessNode(shared_ptr<Node> x) {
    if (x == root) {
      root = nullptr;
      return;
    }
    shared_ptr<Node> parent = x->parent;  // cannot be nullptr
    if (parent->left == x)
      parent->left = nullptr;
    else
      parent->right = nullptr;
  }

  // Preconditions: n has exactly child. Note that x's child must be childless.
  // Does not update: 1) balances above x, 2) subtree_size's above x.
  // Will update: x's subtree size and balance
  void MoveChildInto(shared_ptr<Node> x) {
    if (x == root) {
      if (x->left != nullptr) {
        x->left->parent = nullptr;
        root = x->left;
      } else {
        x->right->parent = nullptr;
        root = x->right;
      }
      return;
    }
    shared_ptr<Node> child = x->left == nullptr ? x->right : x->left;
    shared_ptr<Node> parent = x->parent;
    child->parent = parent;
    if (parent->left == x)
      parent->left = child;
    else
      parent->right = child;
  }

  // Does not update: 1) balances at inorder successor or above, 2)
  // subtree_size's above x.
  // At the end of this function,the returned Node and all ancestor Nodes
  // will have a subtree_size that is exactly Count(x) more than it
  // should be (the subtree_sum will be exactly Count(x) * x->value more than it
  // should be. These will get updated later on in the deletion control flow.
  // Returns the previous parent of the inorder successor's Node.
  shared_ptr<Node> MoveInorderSuccessorInto(shared_ptr<Node> x) {
    ll old_x_subtree_size = Count(x);
    ll old_x_value = x->value;
    shared_ptr<Node> successor = x->right;
    while (successor->left != nullptr) successor = successor->left;
    shared_ptr<Node> successor_original_parent = successor->parent;

    // Copy the successor data into x.
    x->value = successor->value;
    x->subtree_size =
        Count(successor) + x->left->subtree_size + x->right->subtree_size;
    // Update the subtree sizes of all nodes in between the current and old
    // successor nodes (to account for the swap.)
    shared_ptr<Node> nodes_from_successor_to_x = successor->parent;
    while (nodes_from_successor_to_x != x) {
      nodes_from_successor_to_x->subtree_size +=
          old_x_subtree_size - Count(successor);
      nodes_from_successor_to_x->subtree_sum +=
          old_x_value * old_x_subtree_size -
          Count(successor) * successor->value;
      nodes_from_successor_to_x = nodes_from_successor_to_x->parent;
    }

    // Delete old the successor node.
    if (successor->right == nullptr)
      DeleteChildlessNode(successor);  // successor cannot have a left child
    else
      MoveChildInto(successor);

    return successor_original_parent;
  }

  // ROTATIONS =================================================================
  // In the Rotate* functions below, x is the root of the old subtree.
  // Preconditions: balances and counts at x and under must be accurate.
  // Postconditions: balances and counts at x and under will be accurate.
  //
  // x and x->right must be non-null. x->left may be null and x->right may be a
  // leaf. x should have balance +1 or +2.
  void RotateLeft(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->left) - x->right->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->right;
    shared_ptr<Node> t = z->left;
    if (root == x) root = z;
    x->right = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;

    if (x->parent != nullptr) {
      if (x == x->parent->left)
        x->parent->left = z;
      else
        x->parent->right = z;
    }
    z->left = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if ((x->balance == 1 && z->balance == 1) ||
        (x->balance == 2 && z->balance == 2))
      x->balance = -1;
    else if (z->balance == 0 && x->balance == 2)  // only happens with deletion
      x->balance = 1;
    else if (z->balance == 0 && x->balance == 1)  // only happens with deletion
      x->balance = 0;
    else
      x->balance = 0;
    if (old_x_balance == 2 && z->balance == 0)
      z->balance = -1;
    else if (old_x_balance == 2)
      z->balance = 0;
    else if (z->balance >= 0)
      z->balance = -1;
    else
      z->balance = -2;

    z->subtree_size = x->subtree_size;
    z->subtree_sum = x->subtree_sum;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
    x->subtree_sum -= SubtreeSum(z->right) + Count(z) * z->value;
  }

  // x and x->left must be non-null. x->right may be null and x->left may be a
  // leaf. x should have balance -1 or -2.
  void RotateRight(shared_ptr<Node> x) {
    const int num_at_x =
        x->subtree_size - SubtreeSize(x->right) - x->left->subtree_size;

    // Update connections.
    shared_ptr<Node> z = x->left;
    shared_ptr<Node> t = z->right;
    if (root == x) root = z;
    x->left = t;
    if (t != nullptr) t->parent = x;
    z->parent = x->parent;
    if (x->parent != nullptr) {
      if (x == x->parent->right)
        x->parent->right = z;
      else
        x->parent->left = z;
    }
    z->right = x;
    x->parent = z;

    // Update balances.  SUBTLE LOGIC
    const int old_x_balance = x->balance;
    if ((x->balance == -1 && z->balance == -1) ||
        (x->balance == -2 && z->balance == -2))
      x->balance = 1;
    else if (z->balance == 0 && x->balance == -2)  // only happens with deletion
      x->balance = -1;
    else if (z->balance == 0 && x->balance == -1)  // only happens with deletion
      x->balance = 0;
    else
      x->balance = 0;
    if (old_x_balance == -2 && z->balance == 0)
      z->balance = 1;
    else if (old_x_balance == -2)
      z->balance = 0;
    else if (z->balance <= 0)
      z->balance = 1;
    else
      z->balance = 2;

    z->subtree_size = x->subtree_size;
    z->subtree_sum = x->subtree_sum;
    x->subtree_size = SubtreeSize(x->left) + SubtreeSize(x->right) + num_at_x;
    x->subtree_sum -= SubtreeSum(z->left) + Count(z) * z->value;
  }

  shared_ptr<Node> root;
};
/* END LIBRARIES */

int n;
ll t;
vector<ll> a;

void Load() {
  scanf("%d%lld", &n, &t);
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lld", &a[i]);
  }
}

void Solve() {
  vector<ll> pref(n, 0);
  pref[0] = a[0];
  for (int i = 1; i < n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }

  Multiset multiset;
  multiset.Insert(0);
  ll ans = 0, segment_max = t - 1;
  for (int i = 0; i < n; ++i) {
    ll min_pref_sum = pref[i] - segment_max;
    ans += multiset.CountNumAtLeast(min_pref_sum);
    multiset.Insert(pref[i]);
  }
  printf("%lld\n", ans);
}

int main() {
  Load();
  Solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

int n;
ll t;
vector<ll> a;

void Load() {
  scanf("%d%lld", &n, &t);
  a.resize(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lld", &a[i]);
  }
}

void Solve() {
  vector<ll> pref(n, 0);
  pref[0] = a[0];
  for (int i = 1; i < n; ++i) {
    pref[i] = pref[i - 1] + a[i];
  }

  multiset<ll> past_prefixes = {0};
  ll ans = 0, segment_max = t - 1;
  for (int i = 0; i < n; ++i) {
    ll min_pref_sum = pref[i] - segment_max;
    ans +=
        distance(past_prefixes.lower_bound(min_pref_sum), past_prefixes.end());
    past_prefixes.insert(pref[i]);
  }
  printf("%lld\n", ans);
}

int main() {
  Load();
  Solve();
  return 0;
}