#include <bits/stdc++.h>
using namespace std;
long int a[200005];
vector<long> tree[4*200005];
long ans=0;
void mergeSegment(long node,long st,long en,long t){
    if(st>en)
    return;
    if(st==en){
        vector<long> s;
        s.push_back(a[en]);
        if(a[en]<t)
        ans++;
        tree[node]=s;
        return;
    }
    long m=(st+en)/2;
    mergeSegment(2*node+1,st,m,t);
    mergeSegment(2*node+2,m+1,en,t);
    vector<long> ss=tree[2*node+1];
    long n=ss.size()-1;
    long curr=0;
    long pos=-1;
    for(int i=m+1;i<=en;i++){
        curr+=a[i];
        long afford=(t-curr);
        long l=0,h=n;
        while(l<=h){
            long m1=(l+h)/2;
            if(ss[m1]<afford){
                pos=m1;
                l=m1+1;
            }
            else
            h=m1-1;
        }
        ans+=(pos+1);
        pos=-1;
    }
    vector<long> sb;
    long x=0;
    for(int i=en;i>=st;i--){
        x+=a[i];
        sb.push_back(x);
    }
    sort(sb.begin(),sb.end());
    tree[node]=sb;
}
int main() {
    long int n,t;
    cin>>n>>t;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    mergeSegment(0,0,n-1,t);
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
long int a[200005];
vector<long> tree[4*200005];
long long ans=0;
void mergeSegment(long node,long st,long en,long long t){
    if(st>en)
    return;
    if(st==en){
        vector<long> s;
        s.push_back(a[en]);
        if(a[en]<t)
        ans++;
        tree[node]=s;
        return;
    }
    long m=(st+en)/2;
    mergeSegment(2*node+1,st,m,t);
    mergeSegment(2*node+2,m+1,en,t);
    vector<long> ss=tree[2*node+1];
    long n=ss.size()-1;
    long curr=0;
    long pos=-1;
    for(int i=m+1;i<=en;i++){
        curr+=a[i];
        long afford=(t-curr);
        long l=0,h=n;
        while(l<=h){
            long m1=(l+h)/2;
            if(ss[m1]<afford){
                pos=m1;
                l=m1+1;
            }
            else
            h=m1-1;
        }
        ans+=(pos+1);
        pos=-1;
    }
    vector<long> sb;
    long x=0;
    for(int i=en;i>=st;i--){
        x+=a[i];
        sb.push_back(x);
    }
    sort(sb.begin(),sb.end());
    tree[node]=sb;
}
int main() {
    long long int n,t;
    cin>>n>>t;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    mergeSegment(0,0,n-1,t);
    cout<<ans<<endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
vector <long long> pre;
long long n, res = 0, m, run, f[200001];
long long a[200001], s[100001], t;
void update (int p) {
    for (int i = p; i ; i -= i & -i) {
        f[i]++;
    }
}
long long get (int p) {
    long long ans = 0;
    for (int i = p; i <= m; i+= i & -i) {
        ans += f[i];
    }
    return ans;
}
int main () {
    scanf ("%d %I64d", &n, &t);
    pre.push_back(-1e13);
    pre.push_back(0);
    for (int i = 1; i <= n; i++) {
        scanf ("%I64d", &a[i]);
        s[i] = s[i - 1] + a[i];
        pre.push_back(s[i]);
    }
    sort (pre.begin(), pre.end());
    pre.resize(distance(pre.begin(), unique(pre.begin(), pre.end())));
    m = pre.size();
    //vector <long long> :: iterator it;
    //for (it = pre.begin(); it != pre.end(); it++) cout<<*it <<" ";cout<<"\n";
    update(lower_bound(pre.begin(), pre.end(), 0) - pre.begin());
    run = 0;
    for (int i = 1; i <= n; i++) {
        run += a[i];
        int tmp1 = upper_bound(pre.begin(), pre.end(), run - t) - pre.begin();
        if (tmp1  != 0) res += get (tmp1);
        int tmp2 = lower_bound(pre.begin(), pre.end(), run) - pre.begin();
        if (tmp2 != 0 ) update (tmp2);
    }
    printf ("%I64d", res);
}


#include<bits/stdc++.h>
using namespace std;
vector <long long> pre;
long long n, res = 0, m, run, f[200001];
long long a[200001], s[100001], t;
void update (int p) {
    for (int i = p; i ; i -= i & -i) {
        f[i]++;
    }
}
long long get (int p) {
    long long ans = 0;
    for (int i = p; i <= m; i+= i & -i) {
        ans += f[i];
    }
    return ans;
}
int main () {
    scanf ("%d %I64d", &n, &t);
    pre.push_back(0);
    for (int i = 1; i <= n; i++) {
        scanf ("%I64d", &a[i]);
        s[i] = s[i - 1] + a[i];
        pre.push_back(s[i]);
    }
    sort (pre.begin(), pre.end());
    pre.resize(distance(pre.begin(), unique(pre.begin(), pre.end())));
    m = pre.size();
    //vector <long long> :: iterator it;
    //for (it = pre.begin(); it != pre.end(); it++) cout<<*it <<" ";cout<<"\n";
    update(lower_bound(pre.begin(), pre.end(), 0) - pre.begin());
    run = 0;
    for (int i = 1; i <= n; i++) {
        run += a[i];
        int tmp1 = upper_bound(pre.begin(), pre.end(), run - t) - pre.begin();
        res += get (tmp1);
        int tmp2 = lower_bound(pre.begin(), pre.end(), run) - pre.begin();
        update (tmp2);
    }
    printf ("%I64d", res);
}


#include<bits/stdc++.h>
using namespace std;
multiset <long long> se;
int n, res = 0;
long long a[200001], s[100001], t;
int main () {
    scanf ("%d %I64d", &n, &t);
    for (int i = 1; i <= n; i++) {
        scanf ("%I64d", &a[i]);
        s[i] = s[i - 1] + a[i];
    }
    se.insert (0);
    for (int i = 1; i <= n; i++) {
        multiset <long long> :: iterator it;
        it = se.upper_bound(s[i] - t);
        int vt = distance( it, se.end());
        res += vt;
        se.insert (s[i]);
    }
    printf ("%d", res);
}


#include<bits/stdc++.h>
using namespace std;
vector <long long> pre;
long long n, res = 0, m, run, f[200001];
long long a[200001], s[100001], t;
void update (int p) {
    for (int i = p; i ; i -= i & -i) {
        f[i]++;
    }
}
long long get (int p) {
    long long ans = 0;
    for (int i = p; i <= m; i+= i & -i) {
        ans += f[i];
    }
    return ans;
}
int main () {
    scanf ("%d %I64d", &n, &t);
    pre.push_back(0);
    for (int i = 1; i <= n; i++) {
        scanf ("%I64d", &a[i]);
        s[i] = s[i - 1] + a[i];
        pre.push_back(s[i]);
    }
    sort (pre.begin(), pre.end());
    pre.resize(distance(pre.begin(), unique(pre.begin(), pre.end())));
    m = pre.size();
    //vector <long long> :: iterator it;
    //for (it = pre.begin(); it != pre.end(); it++) cout<<*it <<" ";cout<<"\n";
    update(lower_bound(pre.begin(), pre.end(), 0) - pre.begin());
    run = 0;
    for (int i = 1; i <= n; i++) {
        run += a[i];
        int tmp1 = upper_bound(pre.begin(), pre.end(), run - t) - pre.begin();
        if (tmp1 != 0) res += get (tmp1);
        int tmp2 = lower_bound(pre.begin(), pre.end(), run) - pre.begin();
        if (tmp2 != 0) update (tmp2);
    }
    printf ("%I64d", res);
}


#include <bits/stdc++.h>

#define forn(i, n) for (int i = 0; i < int(n); i++)

using namespace std;

const int N = 200 * 1000 + 13;

int n;
long long T;
int a[N];
int f[N];

void upd(int x){
	for (int i = x; i < N; i |= i + 1)
		++f[i];
}

int get(int x){
	int res = 0;
	for (int i = x; i >= 0; i = (i & (i + 1)) - 1)
		res += f[i];
	return res;
}

int main() {
	scanf("%d%lld", &n, &T);
	forn(i, n)
		scanf("%d", &a[i]);

	vector<long long> sums(1, 0ll);
	long long pr = 0;
	forn(i, n){
		pr += a[i];
		sums.push_back(pr);
	}

	sort(sums.begin(), sums.end());
	sums.resize(unique(sums.begin(), sums.end()) - sums.begin());

	long long ans = 0;
	pr = 0;
	upd(lower_bound(sums.begin(), sums.end(), 0ll) - sums.begin());

	forn(i, n){
		pr += a[i];

		int npos = upper_bound(sums.begin(), sums.end(), pr - T) - sums.begin();
		ans += (i + 1 - get(npos - 1));

		int k = lower_bound(sums.begin(), sums.end(), pr) - sums.begin();
		upd(k);
	}

	printf("%lld\n", ans);
	return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll long long int
#define ld long double
#define bitcount __builtin_popcountll
#define ull unsigned long long int
#define mod 1000000007
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define s(n) scanf("%d",&n)
#define sll(n) scanf("%lld",&n)
#define all(v) v.begin(),v.end()
#define p(x) printf("%d ",x)
#define pll(x) printf("%lld",x)
#define debug(x) cout << "> " << #x << " : " << x << "\n";
#define gur_chella ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define N 2010101
#define LN 14
#define infinity 4123456789123456789ll
typedef tree<
ll,
null_type,
less<ll>,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
ll powfi(ll x, ll y, ll p)
{
    ll res = 1;
    x = x % p;
    while (y > 0){
        if (y & 1)
            res = ((res%p)*(x%p)) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res%p;
}
ordered_set s;
ll arr[N],cum[N];
int main()
{
	gur_chella;
	ll n, t, i, j, k;
	cin>>n>>t;
	ll ans=0;
	t--;
	for(i=1;i<=n;i++)
	{
		cin>>arr[i];
		cum[i]=cum[i-1]+arr[i];
		ans+=(i-1) - (s.order_of_key(cum[i]-t));
		//cout<<cum[i]<<" "<<(s.order_of_key(cum[i]-t))<<"\n";
		s.insert(cum[i]);
		ans+=(cum[i]<(t+1));
	}
	cout<<ans;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll long long int
#define ld long double
#define bitcount __builtin_popcountll
#define ull unsigned long long int
#define mod 1000000007
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define s(n) scanf("%d",&n)
#define sll(n) scanf("%lld",&n)
#define all(v) v.begin(),v.end()
#define p(x) printf("%d ",x)
#define pll(x) printf("%lld",x)
#define debug(x) cout << "> " << #x << " : " << x << "\n";
#define gur_chella ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define N 2010101
#define LN 14
#define infinity 4123456789123456789ll
typedef tree<
ld,
null_type,
less<ld>,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
ll powfi(ll x, ll y, ll p)
{
    ll res = 1;
    x = x % p;
    while (y > 0){
        if (y & 1)
            res = ((res%p)*(x%p)) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res%p;
}
ordered_set s;
ld arr[N],cum[N];
int main()
{
	gur_chella;
	ll n, i, j, k;
	ld t;
	cin>>n>>t;
	ll ans=0;
	s.insert(0);
	for(i=1;i<=n;i++)
	{
		cin>>arr[i];
		cum[i]=cum[i-1]+arr[i];
		ans+=(i) - (s.order_of_key(cum[i]-t+0.5));
		s.insert(cum[i]);

	}
	cout<<ans;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll long long int
#define ld long double
#define bitcount __builtin_popcountll
#define ull unsigned long long int
#define mod 1000000007
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define s(n) scanf("%d",&n)
#define sll(n) scanf("%lld",&n)
#define all(v) v.begin(),v.end()
#define p(x) printf("%d ",x)
#define pll(x) printf("%lld",x)
#define debug(x) cout << "> " << #x << " : " << x << "\n";
#define gur_chella ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define N 2010101
#define LN 14
#define infinity 4123456789123456789ll
typedef tree<
pair<ll,ll>,
null_type,
less<pair<ll,ll> >,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
ll powfi(ll x, ll y, ll p)
{
    ll res = 1;
    x = x % p;
    while (y > 0){
        if (y & 1)
            res = ((res%p)*(x%p)) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res%p;
}
ordered_set s;
ll arr[N],cum[N];
int main()
{
	gur_chella;
	ll n, t, i, j, k;
	cin>>n>>t;
	ll ans=0;
	s.insert({0,0});
	for(i=1;i<=n;i++)
	{
		cin>>arr[i];
		cum[i]=cum[i-1]+arr[i];
		ans+=(i) - (s.order_of_key({(cum[i]-t),i}));
		//cout<<i<<" "<<(s.order_of_key(cum[i]-t))<<"\n";
		s.insert({cum[i],i});

	}
	cout<<ans;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll long long int
#define ld long double
#define bitcount __builtin_popcountll
#define ull unsigned long long int
#define mod 1000000007
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define s(n) scanf("%d",&n)
#define sll(n) scanf("%lld",&n)
#define all(v) v.begin(),v.end()
#define p(x) printf("%d ",x)
#define pll(x) printf("%lld",x)
#define debug(x) cout << "> " << #x << " : " << x << "\n";
#define gur_chella ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define N 2010101
#define LN 14
#define infinity 4123456789123456789ll
typedef tree<
ll,
null_type,
less<ll>,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
ll powfi(ll x, ll y, ll p)
{
    ll res = 1;
    x = x % p;
    while (y > 0){
        if (y & 1)
            res = ((res%p)*(x%p)) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res%p;
}
ordered_set s;
ll arr[N],cum[N];
int main()
{
	gur_chella;
	ll n, t, i, j, k;
	cin>>n>>t;
	ll ans=0;

	for(i=1;i<=n;i++)
	{
		cin>>arr[i];
		cum[i]=cum[i-1]+arr[i];
		ans+=(i-1) - (s.order_of_key(cum[i]-t+1));
		s.insert(cum[i]);
		ans+=(cum[i]<(t));
	}
	cout<<ans;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll long long int
#define ld long double
#define bitcount __builtin_popcountll
#define ull unsigned long long int
#define mod 1000000007
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define s(n) scanf("%d",&n)
#define sll(n) scanf("%lld",&n)
#define all(v) v.begin(),v.end()
#define p(x) printf("%d ",x)
#define pll(x) printf("%lld",x)
#define debug(x) cout << "> " << #x << " : " << x << "\n";
#define gur_chella ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define N 2010101
#define LN 14
#define infinity 4123456789123456789ll
typedef tree<
ll,
null_type,
less<ll>,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
ll powfi(ll x, ll y, ll p)
{
    ll res = 1;
    x = x % p;
    while (y > 0){
        if (y & 1)
            res = ((res%p)*(x%p)) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res%p;
}
ordered_set s;
ll arr[N],cum[N];
int main()
{
	gur_chella;
	ll n, t, i, j, k;
	cin>>n>>t;
	ll ans=0;
	s.insert(0);
	for(i=1;i<=n;i++)
	{
		cin>>arr[i];
		cum[i]=cum[i-1]+arr[i];
		ans+=(i) - (s.order_of_key(cum[i]-t+1));
		s.insert(cum[i]);

	}
	cout<<ans;
}


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

// Multiset optimized for querying how many of its elements are at least a
// certain threshold; these queries are O(log n).
class ThresholdMultiset {
  // Implemented as an AVL tree where each node has a counter for its subtree
  // size.
 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;
    }
    // Found k. No need to update balances or do rotations.
    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++;

    // 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->count++;
      }
      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->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);
  }

  // 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 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;
  };

  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);
  }

  // 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;

    // 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.
    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;

    // 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.
    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);
}

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;
  int 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(int 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(int 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(int 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;
  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;

// 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->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;

struct Node {
  explicit Node(ll 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;

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;
  int 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(int 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);
  }

  int CountNumAtLeast(int 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)
  int CountNumAtLeast(int 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;
  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;
}

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");
}

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(ll 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 {
  // Implemented as an AVL tree where each node has a counter for its subtree
  // size.
 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;
    }
    // Found k. No need to update balances or do rotations.
    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++;

    // 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->count++;
      }
      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->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);
  }

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

 private:
  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);
  }

  // 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;

    // 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.
    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;

    // 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.
    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);
}

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;
    }

    // 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 cur.
  void DeleteChildlessNode(shared_ptr<Node> n) {
    if (cur->parent == nullptr) {  // cur is the root
      root = nullptr;
      return;
    }
    shared_ptr<Node> parent = n->parent;
    if (parent->left == n)
      parent->left == nullptr;
    else
      parent->right == nullptr;
  }

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

  // Does not update: 1) balances at inorder successor or above, 2)
  // subtree_size's above cur.
  // 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).
  void MoveInorderSuccessorInto(shared_ptr<Node> n) {
    shared_ptr<Node> successor = cur->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 cur.
    cur->value = successor->value;
    cur->subtree_size = old_successor_subtree_size + cur->left->subtree_size +
                        cur->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_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;
    }

    // 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;
}