#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <string>
#include <sstream>
#include <complex>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <functional>
//#include <bits/stdc++.h>

using namespace std;
typedef long long unsigned int ll;	//10^18
typedef unsigned long ul;

typedef map<ll, ll> m;
typedef multimap<ll, ll> mm;
typedef set<ll> s;
typedef multiset<ll> ms;
typedef priority_queue<ll> pq;
typedef queue<ll> q;
typedef deque<ll> dq;
typedef list<ll> lst;
typedef pair<ll, ll> p;

#define EPS (1e-7)
#define INF (1e9)
#define PI (acos(-1))

//#define and &&
//#define or ||
//#define not !
//#define neq !=
//#define eq ==

#define REP(i, n) for(int i=0;i<n;i++)	// from 0 to n
#define REPR(i, n) for(int i = n;i >= 0;i--)	// from n to 0
#define FOR(i, m, n) for(int i = m;i < n;i++)	// from m to n
#define DBG(a) cout << #a << " : " << a << "\n";
#define MSG(a) cout << a << "\n";
#define ALL(v) v.begin(), v.end()
#define SZ(x) ((int)(x).size())
#define PNT(a) printf("%lld", (a))

#define pb push_back	//配列などの最後に要素を追加
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define F first
#define S second

template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }

int dy[] = { 0, 0, 1, -1, 0 };
int dx[] = { 1, -1, 0, 0, 0 };

//swap(a, b);
//sort(arr, arr + n);	//昇順
//sort(arr, arr+n, greater<int>());	//降順
//max(a, b);
//min(a, b);

//upper_bound(a, a+n, k)	//配列aの中で、kより大きい値が初めて現れる位置へのポインタ
//upper_bound(ALL(v), k)	//STLvの中で、kより大きい値が初めて現れる位置へのポインタ
//lower_bound(a, a+n, k)
//lower_bound(ALL(v), k)	//STLvの中で、kの以上値が初めて現れる位置へのポインタ
//lower_bound(ALL(v),k) - upper_bound(ALL(v),k)	//二分探索を用いて、ある列aに含まれる数kの個数を求める

// n個のデータをvectorで取得
vector<ll> INV(ll n) {
	vector<ll> v(n);
	REP(i, n)	cin >> v[i];
	return v;
}


// index が条件を満たすかどうか
bool isOK(vector<ll>& v, int index, int key) {
	if (v[index] >= key) return true;
	else return false;
}

// 汎用的な二分探索	
ll bs(vector<ll>& v, int key) {
	int ng = -1; //「index = 0」が条件を満たすこともあるので、初期値は -1
	int ok = SZ(v); // 「index = a.size()-1」が条件を満たさないこともあるので、初期値は a.size()

	/* ok と ng のどちらが大きいかわからないことを考慮 */
	while (abs(ok - ng) > 1) {
		int mid = (ok + ng) / 2;

		if (isOK(v, mid, key)) ok = mid;
		else ng = mid;
	}
	return ok;
}

// 最大公約数
ll gcd(ll a, ll b) {
	if (a < b)	swap(a, b);
	ll r = a % b;
	while (r != 0) {
		a = b;
		b = r;
		r = a % b;
	}
	return b;

}

// 素因数分解 
// cnt_pf[i]にi+1で割った回数を格納している
// cnt_pf[0]に入力が素数だった場合に1が入る
vector<ll> prime_factorization(ll n) {
	vector<ll> cnt_pf(ceil(sqrt(n)), 0);
	FOR(i, 1, SZ(cnt_pf)) {
		while (n % (i+1) == 0) {
			cnt_pf[i]++;
			n /= (i+1);
		}
		if (n == 1)	break;
	}
	if (n != 1) {
		cnt_pf[0]++;
	}
	return cnt_pf;
}

//
// main関数
//

signed main()
{
	//cin.tie(0);
	//ios::sync_with_stdio(false);

	// 文字列取得
	//string s;
	//cin >> s;
	
	// 変数（scala）取得
	ll n;
	cin >> n;


	// 変数（vector）取得
	//vector<ll> a(n);
	//a = INV(n);

	//
	// 実装部分
	//
	ll ans=n*(n-1)/2;

	//
	// 実装部分おわり
	//

	// 解答出力
	PNT(ans);

	return 0;
}

Measured memory_bytes: 256