#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <functional>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <climits>
#include <sstream>

using namespace std;
#define ll long long
#define x first
#define y second
#define pii pair<int, int>
#define pdd pair<double, double>
#define pil pair<int, ll>
#define L(s) (int)(s).size()
#define VI vector<int>
#define all(s) (s).begin(), (s).end()
#define pb push_back
#define mp make_pair
#define inf 1000000000
#define pi 3.14159265358979323426264

#define sqr(x) ((x) * (x))
#define REP(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define REPD(i, n) for (int (i) = (n) - 1; (i) >= 0; (i)--)
#define FOR(i, a, b) for (int (i) = (a); (i) < (b); (i)++)
#define FORD(i,a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define FORI(it, cont) for (auto (it) = (cont).begin(); (it) != (cont).end(); (it)++)
#define eps std::numeric_limits<double>::epsilon()

struct ring
{
   int a;
   int b;
   long long h;
};

bool compareByH(const ring& one, const ring& two)
{
   if (one.b == two.b)
   {
      return one.a > two.a;
   }
   return one.b > two.b;
}

bool greaterPair(const pil& one, const pil& two)
{
   return one.x > two.x;
}

bool lessPair(const pil& one, const pil& two)
{
   return one.x < two.x;
}

int main()
{
   int n;
   cin >> n;
   vector<ring> rings(n);
   REP(i, n)
   {
      cin >> rings[i].a >> rings[i].b >> rings[i].h;
   }
   sort(all(rings), compareByH);
   map<int, long long> heights;
   heights[0] = 0;
   REP(i, n)
   {
      ring& curRing = rings[i];
      auto it = heights.end();
      it--;
      while (it->first >= curRing.b)
      {
         it--;
      }
      if (it->first >= 0)
      {
         ll newHeight = it->second + curRing.h;
         auto aIt = lower_bound(all(heights), mp(curRing.a,0), lessPair);
         while (aIt != heights.end())
         {
            auto next = aIt;
            next++;
            if (aIt->second < newHeight)
            {
               heights.erase(aIt);
            }
            else
            {
               break;
            }
            aIt = next;
         }
         auto f = heights.find(curRing.a);
         if (f == heights.end() || f->second < newHeight)
         {
            heights[curRing.a] = newHeight;
         }
      }
   }

   long long maxH = 0;
   FORI(it, heights)
   {
      if (it->second > maxH)
      {
         maxH = it->second;
      }
   }
   cout << maxH << endl;
   return 0;
}


#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <functional>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <climits>
#include <sstream>

using namespace std;
#define ll long long
#define x first
#define y second
#define pii pair<int, int>
#define pdd pair<double, double>
#define pil pair<int, ll>
#define L(s) (int)(s).size()
#define VI vector<int>
#define all(s) (s).begin(), (s).end()
#define pb push_back
#define mp make_pair
#define inf 1000000000
#define pi 3.14159265358979323426264

#define sqr(x) ((x) * (x))
#define REP(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define REPD(i, n) for (int (i) = (n) - 1; (i) >= 0; (i)--)
#define FOR(i, a, b) for (int (i) = (a); (i) < (b); (i)++)
#define FORD(i,a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define FORI(it, cont) for (auto (it) = (cont).begin(); (it) != (cont).end(); (it)++)
#define eps std::numeric_limits<double>::epsilon()

struct ring
{
   int a;
   int b;
   long long h;
};

bool compareByH(const ring& one, const ring& two)
{
   return one.b > two.b;
}

bool greaterPair(const pil& one, const pil& two)
{
   return one.x > two.x;
}

bool lessPair(const pil& one, const pil& two)
{
   return one.x < two.x;
}

int main()
{
   int n;
   cin >> n;
   vector<ring> rings(n);
   REP(i, n)
   {
      cin >> rings[i].a >> rings[i].b >> rings[i].h;
   }
   sort(all(rings), compareByH);
   map<int, long long> heights;
   heights[0] = 0;
   REP(i, n)
   {
      ring& curRing = rings[i];
      auto it = heights.end();
      it--;
      while (it->first >= curRing.b)
      {
         it--;
      }
      if (it->first >= 0)
      {
         ll newHeight = it->second + curRing.h;
         auto aIt = lower_bound(all(heights), mp(curRing.a,0), lessPair);
         while (aIt != heights.end() && aIt->first >= it->first)
         {
            if (aIt->second < newHeight)
            {
               aIt->second = newHeight;
            }
            aIt++;
         }
         heights[curRing.a] = newHeight;
      }
   }

   long long maxH = 0;
   FORI(it, heights)
   {
      if (it->second > maxH)
      {
         maxH = it->second;
      }
   }
   cout << maxH << endl;
   return 0;
}


#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <functional>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <climits>
#include <sstream>

using namespace std;
#define ll long long
#define x first
#define y second
#define pii pair<int, int>
#define pdd pair<double, double>
#define L(s) (int)(s).size()
#define VI vector<int>
#define all(s) (s).begin(), (s).end()
#define pb push_back
#define mp make_pair
#define inf 1000000000
#define pi 3.14159265358979323426264

#define sqr(x) ((x) * (x))
#define REP(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define REPD(i, n) for (int (i) = (n) - 1; (i) >= 0; (i)--)
#define FOR(i, a, b) for (int (i) = (a); (i) < (b); (i)++)
#define FORD(i,a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define FORI(it, cont) for (auto (it) = (cont).begin(); (it) != (cont).end(); (it)++)
#define eps std::numeric_limits<double>::epsilon()

struct ring
{
   int a;
   int b;
   int h;
};

bool compareByH(const ring& one, const ring& two)
{
   return one.b > two.b;
}

bool greaterPair(const pii& one, const pii& two)
{
   return one.x > two.x;
}

bool lessPair(const pii& one, const pii& two)
{
   return one.x < two.x;
}

int main()
{
   int n;
   cin >> n;
   vector<ring> rings(n);
   REP(i, n)
   {
      cin >> rings[i].a >> rings[i].b >> rings[i].h;
   }
   sort(all(rings), compareByH);
   map<int, int> heights;
   heights[0] = 0;
   REP(i, n)
   {
      ring& curRing = rings[i];
      auto it = heights.end();
      it--;
      while (it->first > curRing.b)
      {
         it--;
      }
      if (it->first >= 0)
      {
         int newHeight = it->second + curRing.h;
         auto aIt = lower_bound(all(heights), mp(curRing.a,0), lessPair);
         while (aIt != heights.end() && aIt->first >= it->first)
         {
            if (aIt->second < newHeight)
            {
               aIt->second = newHeight;
            }
            aIt++;
         }
         heights[curRing.a] = newHeight;
      }
   }

   int maxH = 0;
   FORI(it, heights)
   {
      if (it->second > maxH)
      {
         maxH = it->second;
      }
   }
   cout << maxH << endl;
   return 0;
}


aux = [(9e9, 0, 0)]
n = int(input())

for i in range(n):
    a, b, h = map(int, input().split())
    aux.append((b, a, h)) #sort padrao eh pelo item 0 da tupla

aux.sort(reverse=True)

s, p = [0], [0] *(n + 1)

for i in range(1, n + 1):
    while aux[s[-1]][1] >= aux[i][0]:
        s.pop()

    p[i] = p[s[-1]] + aux[i][2]
    s.append(i)
print(max(p))


aux = [(9e9, 0, 0)]
n = int(input())

for i in range(n):
    a, b, h = map(int, input().split())
    aux.append((b, a, h)) #sort padrao eh pelo item 0 da tupla

aux.sort(reverse=True)

s, p = [0], [0] *(n + 1)

for i in range(1, n + 1):
    while aux[s[-1]][1] >= aux[i][0]:
        s.pop()

    p[i] = p[s[-1]] + aux[i][2]
    s.append(i)

print(max(p))


import operator
n = int(input())
arr=[]
for i in range(n):
    arr.append([int(element) for element in input().seqplit()])
arr = sorted(arr, key=operator.itemgetter(1,0,2), reverseqe= True)
heigh = [0 for i in range(n)]
seq = []
for i in range(n):
    while len(seq) > 0 and arr[seq[-1]][0] >= arr[i][1] :
        seq.pop()
    if len(seq) > 0 :
        heigh[i] = heigh[seq[-1]]
    heigh[i] += arr[i][2]
    seq.append(i)
print(max(heigh))


import operator
n = int(input())
arr=[]
for i in range(n):
    arr.append([int(element) for element in input().split()])
arr = sorted(arr, key=operator.itemgetter(1,0,2), reverse= True)
heigh = [0 for i in range(n)]
seq = []
for i in range(n):
    while len(seq) > 0 and arr[seq[-1]][0] >= arr[i][1] :
        seq.pop()
    if len(seq) > 0 :
        heigh[i] = heigh[seq[-1]]
    heigh[i] += arr[i][2]
    seq.append(i)
print(max(heigh))


import operator
n = int(input())
arr=[]
for i in range(n):
    arr.append([int(element) for element in input().split()])
arr = sorted(arr, key=operator.itemgetter(1,0,2), reverse= True)
heigh = [0 for i in range(n)]
s = []
for i in range(n):
    if len(s) > 0 and arr[s[-1]][0] >= arr[i][1] :
        s.clear()
    if len(s) > 0 :
        heigh[i] = heigh[s[-1]]
    heigh[i] += arr[i][2]
    s.append(i)
print(max(heigh))


n = int(input())
d = []
for i in range(n):
    a, b, h = map(int, input().split())
    d.append((b, a, h))

d.sort()

ht = d[len(d) - 1][2]

ans = ht

s = []
s.append(d[len(d) - 1])

for i in range(n - 2, -1, -1):
    while s and d[i][0] <= s[len(s) - 1][1]:
        ht -= s.pop()[2]
    s.append(d[i])
    ht += d[i][2]
    if ans < ht:
        ans = ht

print(ans)


n = int(input())
d = []
for i in range(n):
    a, b, h = map(int, input().split())
    d.append((b, a, h))

d.sort()

ht = d[len(d) - 1][2]

ans = ht

s = []
s.append(d[len(d) - 1])

for i in range(n - 2, -1, -1):
    while s and d[i][0] < s[len(s) - 1][1]:
        dh = s.pop()[2]
        ht -= dh
    s.append(d[i])
    ht += d[i][2]
    if ans < ht:
        ans = ht

print(ans)


from operator import attrgetter, itemgetter
n = int(input());
arr = [[int(x) for x in input().split(' ')] for y in range(n)];
arr = sorted(arr, key=itemgetter(1,0,2), reverse=True);
dp = [0 for x in range(n)];
s = [];
for i in range(n):
	while (s != [] and arr[s[-1]][0] >= arr[i][1]):
		s.pop();
	if (s != []):
		dp[i] = dp[s[-1]];
	dp[i] += arr[i][2];
	s.append(i);
print(max(dp));


from operator import itemgetter, attrgetter
tree = [0 for x in range(4*111111)];

def query(l, r, ql, qr, idx):
	if (ql == l and qr == r):
		return tree[idx];
	mid = l + (r-l)//2;
	if (qr < mid+1):
		return query(l, mid, ql, qr, 2*idx+1);
	elif (ql > mid):
		return query(mid+1, r, ql, qr, 2*idx+2);
	temp1 = query(l, mid, ql, mid, 2*idx+1);
	temp2 = query(mid+1, r, mid+1, qr, 2*idx+2);
	return max(temp1, temp2);

def update(l, r, pos, val, idx):
	if (l == r):
		tree[idx] = val;
		return ;
	mid = l + (r-l)//2;
	if (pos < mid+1):
		update(l, mid, pos, val, 2*idx+1);
	else:
		update(mid+1, r, pos, val, 2*idx+2);
	tree[idx] = max(tree[2*idx+1], tree[2*idx+2]);

inf = (1 << 30);
n = int(input());
arr = [[int(x) for x in input().split(' ')] for y in range(n)];
arr = sorted(arr, key=itemgetter(1, 0, 2), reverse=True);
a_sorted = [[arr[i][0], i] for i in range(n)];
a_sorted += [[-inf, -1]];
a_sorted = sorted(a_sorted, key=itemgetter(0, 1), reverse=True);
b_a = [-1 for i in range(n)];
for i in range(n):
	b_a[a_sorted[i][1]] = i;
for i in range(n):
	x = arr[i][1];
	l = 0; r = n;
	while (l < r):
		mid = l + (r-l)//2;
		if (a_sorted[mid][0] < x):	#pred
			r = mid;
		else:
			l = mid+1;
	temp = query(0, n, l, n, 0);
	res = arr[i][2] + temp;
	update(0, n, b_a[i], res, 0);
print(query(0, n, 0, n, 0));


from bisect import bisect
t = []
for i in range(int(input())):
    a, b, h = map(int, input().split())
    t.append((-b, a, h))
t.sort()
s = [(0, 0), (7e9, 7e9)]
for b, a, h in t:
    i = bisect(s, (-b,))
    h += s[i - 1][1]
    j = bisect(s, (a,))
    while s[j][1] <= h: s.pop(j)
    s.insert(j, (a, h))
print(s[-2][1])


t = [(9e9, 0, 0)]
n = int(input())
for i in range(n):
    a, b, h = map(int, input().split())
    t.append((b, a, h))
t.sort(reverse=True)
s, p = [0], [0] * (n + 1)
for i in range(1, n + 1):
    while t[s[-1]][1] >= t[i][0]: s.pop()
    p[i] = p[s[-1]] + t[i][2]
    s.append(i)
print(max(p))


n = int(input())
d = []
for i in range(n):
    a, b, h = map(int, input().split())
    d.append((b, a, h))
d.sort()
ht = d[len(d) - 1][2]
ans = ht
s = [d[len(d) - 1]]

for i in range(n - 2, -1, -1):
    while s and d[i][0] <= s[len(s) - 1][1]:
        ht -= s.pop()[2]
    s.append(d[i])
    ht += d[i][2]
    if ans < ht:
        ans = ht
print(ans)


#!/usr/bin/env python3
def ri():
    return map(int, input().split())

n = int(input())

r = []
T = []
maxt = -1
for i in range(n):
    r.append(list(ri()))

r.sort(key=lambda e: (e[1], e[0]))

T.append([r[0][2], r[0][1]])
for i in range(1, n):
    tmp = r[i][2]
    l = len(T)
    for j in range(l):
        if r[i][0] >= T[-1][1]:
            T.append([tmp, r[i][1]])
            break
        else:
            tmp = max(T[-1][0]+r[i][2], tmp)
            T.pop()
    else:
        T.append([tmp, r[i][1]])

print(max(T)[0])


using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Numerics;
using static Template;
using static System.Console;
using static System.Convert;
using static System.Math;
using Pi = Pair<int, int>;

class Solver
{
    public void Solve(Scanner sc)
    {
        var N = sc.Int;
        var abh = new int[N][];
        var cm = new List<int>();
        for(int i = 0; i < N; i++)
        {
            abh[i] = sc.ArrInt;
            cm.Add(abh[i][0]);cm.Add(abh[i][1]);
        }
        var dic = Compression(cm.ToArray());
        Array.Sort(abh, (a, b) => b[1] - a[1]);
        var seg = new SegmentTree<long>(N<<1, 0, Max, Max);
        var res = 0L;
        for(int i = 0; i < N; i++)
        {
            var max = seg.Query(0, dic[abh[i][1]]);
            var t = max + abh[i][2];
            chmax(ref res, t);
            seg.Update(dic[abh[i][0]], t);
        }
        WriteLine(res);
    }

    public static Dictionary<T, int> Compression<T>(T[] ar, int d = 0, Comparison<T> cmp = null)
    {
        cmp = cmp ?? Comparer<T>.Default.Compare;
        var dic = new Dictionary<T, int>();
        var cp = new T[ar.Length];
        Array.Copy(ar, cp, ar.Length);
        Array.Sort(cp, (a, b) => cmp(a, b));
        for (var i = 0; i < cp.Length; i++)
            if (!dic.ContainsKey(cp[i]))
                dic[cp[i]] = d++;
        return dic;
    }
}

public class SegmentTree<T>
{
    protected readonly T[] data;
    protected readonly int size;
    protected readonly Func<T, T, T> merge;
    protected readonly Func<T, T, T> update;
    protected readonly T idT;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    protected int Parent(int i)
        => (i - 1) >> 1;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    protected int Left(int i)
        => (i << 1) + 1;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    protected int Right(int i)
        => (i + 1) << 1;
    public T this[int i]
    {
        get { return data[i + size - 1]; }
        set { data[i + size - 1] = value; }
    }

    public SegmentTree(int N, T idT, Func<T, T, T> merge, Func<T, T, T> update = null)
    {
        this.size = 1;
        this.idT = idT;
        this.merge = merge;
        this.update = update ?? ((T val1, T val2) => val2);
        while (size < N)
            size <<= 1;
        data = new T[2 * this.size - 1];
        for (var i = 0; i < 2 * size - 1; i++)
            data[i] = idT;
    }

    public void Update(int i, T value)
    {
        i += size - 1;
        data[i] = update(data[i], value);
        while (i > 0)
        {
            i = Parent(i);
            data[i] = merge(data[Left(i)], data[Right(i)]);
        }
    }

    public void Build()
    {
        for (int i = size - 2; i >= 0; i--)
            data[i] = merge(data[Left(i)], data[Right(i)]);
    }

    public virtual T Query(int left, int right, int k = 0, int l = 0, int r = -1)
    {
        if (r == -1) r = size;
        if (r <= left || right <= l) return idT;
        if (left <= l && r <= right) return data[k];
        else
            return merge(Query(left, right, Left(k), l, (l + r) >> 1), Query(left, right, Right(k), (l + r) >> 1, r));
    }

    /// <summary>
    /// check(func(item[st]...item[i]))がtrueとなる最小のi
    /// </summary>
    public int Find(int st, Func<T, bool> check)
    {
        var x = idT;
        return Find(st, check, ref x, 0, 0, size);
    }
    private int Find(int st, Func<T, bool> check, ref T x, int k, int l, int r)
    {
        if (l + 1 == r)
        { x = merge(x, data[k]); return check(x) ? k - size + 1 : -1; }
        var m = (l + r) >> 1;
        if (m <= st) return Find(st, check, ref x, Right(k), m, r);
        if (st <= l && !check(merge(x, data[k])))
        { x = merge(x, data[k]); return -1; }
        var xl = Find(st, check, ref x, Left(k), l, m);
        if (xl >= 0) return xl;
        return Find(st, check, ref x, Right(k), m, r);
    }
}
#region Template
public static class Template
{
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver().Solve(new Scanner());
        Console.Out.Flush();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) == 1) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) == -1) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static T Unify<T>(this T[] A, Func<T, T, T> f, T init = default(T)) { for (var i = 0; i < A.Length; i++) init = f(init, A[i]); return init; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}

public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    //public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    //public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    //public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}
public class Pair<T1, T2> : IComparable<Pair<T1, T2>>
{
    public T1 v1;
    public T2 v2;
    public Pair() { }
    public Pair(T1 v1, T2 v2)
    { this.v1 = v1; this.v2 = v2; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2> p)
    {
        var c = Comparer<T1>.Default.Compare(v1, p.v1);
        if (c == 0)
            c = Comparer<T2>.Default.Compare(v2, p.v2);
        return c;
    }
    public override string ToString() => $"{v1.ToString()} {v2.ToString()}";
    public void Deconstruct(out T1 a, out T2 b) { a = v1; b = v2; }
}

public class Pair<T1, T2, T3> : Pair<T1, T2>, IComparable<Pair<T1, T2, T3>>
{
    public T3 v3;
    public Pair() : base() { }
    public Pair(T1 v1, T2 v2, T3 v3) : base(v1, v2)
    { this.v3 = v3; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2, T3> p)
    {
        var c = base.CompareTo(p);
        if (c == 0)
            c = Comparer<T3>.Default.Compare(v3, p.v3);
        return c;
    }
    public override string ToString() => $"{base.ToString()} {v3.ToString()}";
    public void Deconstruct(out T1 a, out T2 b, out T3 c) { Deconstruct(out a, out b); c = v3; }
}
#endregion


using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Numerics;
using static Template;
using static System.Console;
using static System.Convert;
using static System.Math;
using Pi = Pair<int, int>;

class Solver
{
    public void Solve(Scanner sc)
    {
        var N = sc.Int;
        var abh = new int[N][];
        var cm = new List<int>();
        for(int i = 0; i < N; i++)
        {
            abh[i] = sc.ArrInt;
            cm.Add(abh[i][0]);cm.Add(abh[i][1]);
        }
        var dic = Compression(cm.ToArray());
        Array.Sort(abh, (a, b) => {
            if (a[1] == b[1]) return b[0] - a[0];
            return b[1] - a[1];
        });
        var seg = new SegmentTree<long>(N<<1, 0, Max, Max);
        var res = 0L;
        for(int i = 0; i < N; i++)
        {
            var max = seg.Query(0, dic[abh[i][1]]);
            var t = max + abh[i][2];
            chmax(ref res, t);
            seg.Update(dic[abh[i][0]], t);
        }
        WriteLine(res);
    }

    public static Dictionary<T, int> Compression<T>(T[] ar, int d = 0, Comparison<T> cmp = null)
    {
        cmp = cmp ?? Comparer<T>.Default.Compare;
        var dic = new Dictionary<T, int>();
        var cp = new T[ar.Length];
        Array.Copy(ar, cp, ar.Length);
        Array.Sort(cp, (a, b) => cmp(a, b));
        for (var i = 0; i < cp.Length; i++)
            if (!dic.ContainsKey(cp[i]))
                dic[cp[i]] = d++;
        return dic;
    }
}

public class SegmentTree<T>
{
    protected readonly T[] data;
    protected readonly int size;
    protected readonly Func<T, T, T> merge;
    protected readonly Func<T, T, T> update;
    protected readonly T idT;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    protected int Parent(int i)
        => (i - 1) >> 1;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    protected int Left(int i)
        => (i << 1) + 1;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    protected int Right(int i)
        => (i + 1) << 1;
    public T this[int i]
    {
        get { return data[i + size - 1]; }
        set { data[i + size - 1] = value; }
    }

    public SegmentTree(int N, T idT, Func<T, T, T> merge, Func<T, T, T> update = null)
    {
        this.size = 1;
        this.idT = idT;
        this.merge = merge;
        this.update = update ?? ((T val1, T val2) => val2);
        while (size < N)
            size <<= 1;
        data = new T[2 * this.size - 1];
        for (var i = 0; i < 2 * size - 1; i++)
            data[i] = idT;
    }

    public void Update(int i, T value)
    {
        i += size - 1;
        data[i] = update(data[i], value);
        while (i > 0)
        {
            i = Parent(i);
            data[i] = merge(data[Left(i)], data[Right(i)]);
        }
    }

    public void Build()
    {
        for (int i = size - 2; i >= 0; i--)
            data[i] = merge(data[Left(i)], data[Right(i)]);
    }

    public virtual T Query(int left, int right, int k = 0, int l = 0, int r = -1)
    {
        if (r == -1) r = size;
        if (r <= left || right <= l) return idT;
        if (left <= l && r <= right) return data[k];
        else
            return merge(Query(left, right, Left(k), l, (l + r) >> 1), Query(left, right, Right(k), (l + r) >> 1, r));
    }

    /// <summary>
    /// check(func(item[st]...item[i]))がtrueとなる最小のi
    /// </summary>
    public int Find(int st, Func<T, bool> check)
    {
        var x = idT;
        return Find(st, check, ref x, 0, 0, size);
    }
    private int Find(int st, Func<T, bool> check, ref T x, int k, int l, int r)
    {
        if (l + 1 == r)
        { x = merge(x, data[k]); return check(x) ? k - size + 1 : -1; }
        var m = (l + r) >> 1;
        if (m <= st) return Find(st, check, ref x, Right(k), m, r);
        if (st <= l && !check(merge(x, data[k])))
        { x = merge(x, data[k]); return -1; }
        var xl = Find(st, check, ref x, Left(k), l, m);
        if (xl >= 0) return xl;
        return Find(st, check, ref x, Right(k), m, r);
    }
}
#region Template
public static class Template
{
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver().Solve(new Scanner());
        Console.Out.Flush();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) == 1) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) == -1) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static T Unify<T>(this T[] A, Func<T, T, T> f, T init = default(T)) { for (var i = 0; i < A.Length; i++) init = f(init, A[i]); return init; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}

public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    //public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    //public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    //public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}
public class Pair<T1, T2> : IComparable<Pair<T1, T2>>
{
    public T1 v1;
    public T2 v2;
    public Pair() { }
    public Pair(T1 v1, T2 v2)
    { this.v1 = v1; this.v2 = v2; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2> p)
    {
        var c = Comparer<T1>.Default.Compare(v1, p.v1);
        if (c == 0)
            c = Comparer<T2>.Default.Compare(v2, p.v2);
        return c;
    }
    public override string ToString() => $"{v1.ToString()} {v2.ToString()}";
    public void Deconstruct(out T1 a, out T2 b) { a = v1; b = v2; }
}

public class Pair<T1, T2, T3> : Pair<T1, T2>, IComparable<Pair<T1, T2, T3>>
{
    public T3 v3;
    public Pair() : base() { }
    public Pair(T1 v1, T2 v2, T3 v3) : base(v1, v2)
    { this.v3 = v3; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2, T3> p)
    {
        var c = base.CompareTo(p);
        if (c == 0)
            c = Comparer<T3>.Default.Compare(v3, p.v3);
        return c;
    }
    public override string ToString() => $"{base.ToString()} {v3.ToString()}";
    public void Deconstruct(out T1 a, out T2 b, out T3 c) { Deconstruct(out a, out b); c = v3; }
}
#endregion


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! min {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b < *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! max {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b > *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: v!([]), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = v!([8]);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn vvb(&mut self, r: usize, c: Option<usize>) -> Vec<Vec<u8>> {
		let mut res = v!([r]);
		let c = c.unwrap_or(0);
		rep!{[r]
			let t = self.vb();
			assert!(c == 0 || t.len() == c);
			res.push(t);
		}
		res
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
	fn graph(&mut self, n: usize, m: usize) -> Vec<Vec<usize>> {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); e[a].push(b); e[b].push(a); } e
	}
	fn graph_w<T: Copy+FromStr>(&mut self, n: usize, m: usize) -> Vec<Vec<(usize,T)>> where T::Err: Debug {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); let c: T = self.p(); e[a].push((b,c)); e[b].push((a,c)); } e
	}
}
//------------------- End rusT }}}

// Segtree base {{{
#[allow(dead_code)]
mod lazy_segtree
{
	pub struct Node<V,L> { pub v: V, pub l: Option<L>, pub b: B, pub ch: CH<Self> }
	impl<V,L> Node<V,L> {
		pub fn new(v: V, b: B) -> Self { Node { v, l: None, b, ch: None } }
		pub fn is_leaf(&self) -> bool { self.ch.is_none() }
		pub fn is_up_to_date(&self) -> bool { self.l.is_none() }
		pub fn len(&self) -> usize { self.b.1 - self.b.0 + 1 }
	}
	pub type B = (usize, usize);
	pub type CH<T> = Option<(*mut T, *mut T)>;
	pub type N<T> = Node<<T as LSTNode>::V,<T as LSTNode>::L>;
	pub trait LSTNode {
		type V: Clone; type L: Clone; type R;
		fn accum_result(res: &mut Self::V, v: &Self::V) {
			*res = Self::combine_values(res, v);
		}
		fn update_parent_value(n: &mut N<Self>) {
			assert!(n.ch.is_some());
			let (lc,rc) = n.ch.unwrap();
			n.v = Self::combine_values(unsafe {&(*lc).v}, unsafe {&(*rc).v});
		}
		fn build_parent_value(n: &mut N<Self>) {
			Self::update_parent_value(n);
		}
		fn update_lazy(n: &mut N<Self>, l: &mut Self::L, fw: bool) {
			Self::augment_lazy(n, l, fw);
			Self::change_lazy_from_node(n, l, fw);
		}
		fn update_children_lazy(n: &mut N<Self>) {
			assert!(n.ch.is_some());
			let (lc,rc) = n.ch.unwrap();
			if let Some(mut l) = n.l.take() {
				Self::update_lazy(unsafe {&mut*lc}, &mut l, true);
				Self::update_lazy(unsafe {&mut*rc}, &mut l, true);
			}
		}
		fn def_value() -> Self::V;
		fn extract_result(res: &Self::V) -> Self::R;
		fn combine_values(_: &Self::V, _: &Self::V) -> Self::V;
		fn reverse_value(_: &Self::V) -> Self::V;
		fn update_value_from_lazy(_: &mut N<Self>);
		fn change_lazy_from_node(_: &N<Self>, _: &mut Self::L, _: bool);
		fn augment_lazy(_: &mut N<Self>, _: &Self::L, _: bool);
	}
	struct UpInfo<'a,L> { l: usize, r: usize, lz: &'a mut L }
	struct QuInfo<V> { l: usize, r: usize, res: V }
	pub struct LST<T: LSTNode> { nodes: Vec<N<T>>, size: usize }
	impl<T: LSTNode> LST<T> {
		pub fn new() -> Self {
			Self { nodes: Vec::new(), size: 0 }
		}
		pub fn init_def(&mut self, s: usize) {
			self.init(vec![T::def_value(); s]);
		}
		pub fn init(&mut self, vals: Vec<T::V>) {
			self.size = vals.len(); self.nodes.clear();
			if self.size > 0 { self.init_nodes(vals); }
		}
		pub fn update(&mut self, l: usize, r: usize, lz: &mut T::L, fw: bool) {
			assert!(l <= r && r < self.size);
			Self::internal_update(unsafe {&mut*self.root()}, &mut UpInfo {l,r,lz}, fw);
		}
		pub fn query_val(&mut self, l: usize, r: usize) -> T::V {
			assert!(l <= r && r < self.size);
			let mut x = QuInfo { l, r, res: T::def_value() };
			Self::internal_query(unsafe {&mut*self.root()}, &mut x);
			x.res
		}
		pub fn query(&mut self, l: usize, r: usize) -> T::R {
			T::extract_result(&self.query_val(l,r))
		}
		fn seg_push(n: &mut N<T>) {
			if !n.is_up_to_date() {
				T::update_value_from_lazy(n);
				if n.ch.is_some() {
					T::update_children_lazy(n);
				}
				n.l = None;
			}
		}
		fn seg_merge(n: &mut N<T>) {
			if let Some((lc,rc)) = n.ch {
				Self::seg_push(unsafe {&mut*lc});
				Self::seg_push(unsafe {&mut*rc});
				T::update_parent_value(n);
			}
		}
		fn internal_update(n: &mut N<T>, x: &mut UpInfo<T::L>, fw: bool) {
			if x.l <= n.b.0 && n.b.1 <= x.r {
				T::update_lazy(n, &mut x.lz, fw);
				Self::seg_push(n);
			} else if x.l <= n.b.1 && n.b.0 <= x.r {
				Self::seg_push(n);
				let (lc,rc) = n.ch.unwrap();
				let (c0,c1) = if fw {(lc,rc)} else {(rc,lc)};
				Self::internal_update(unsafe {&mut*c0}, x, fw);
				Self::internal_update(unsafe {&mut*c1}, x, fw);
				Self::seg_merge(n);
			}
		}
		fn internal_query(n: &mut N<T>, x: &mut QuInfo<T::V>) {
			if x.l <= n.b.0 && n.b.1 <= x.r {
				Self::seg_push(n);
				T::accum_result(&mut x.res, &n.v);
			} else if x.l <= n.b.1 && n.b.0 <= x.r {
				let (lc,rc) = n.ch.unwrap();
				Self::seg_push(n);
				Self::internal_query(unsafe {&mut*lc}, x);
				Self::internal_query(unsafe {&mut*rc}, x);
				Self::seg_merge(n);
			}
		}
		fn init_nodes(&mut self, vals: Vec<T::V>) {
			let sz = 2 * self.size - 1;
			self.nodes.reserve(sz);
			let mut q = Vec::new();
			q.push((0, self.size - 1));
			while let Some((l,r)) = q.pop() {
				if l == r {
					let v = vals[l].clone();
					self.nodes.push(N::<T>::new(v, (l,r)));
				} else {
					let m = l + (r - l + 1) / 2;
					q.push((m, r));
					q.push((l, m - 1));
					let id = self.nodes.len();
					let v = T::def_value();
					let p = self.nodes.as_mut_ptr();
					let lc = unsafe { p.add(id + 1) };
					let rc = unsafe { p.add(id + 2 * (m - l)) };
					self.nodes.push(N::<T> { v, l: None, b: (l,r), ch: Some((lc,rc)) });
				}
			}
			assert_eq!(self.nodes.len(), sz);
			for n in self.nodes.iter_mut().rev() {
				if !n.is_leaf() {
					T::build_parent_value(n);
				}
			}
		}
		fn root(&mut self) -> *mut N<T> {
			assert!(!self.nodes.is_empty());
			self.nodes.as_mut_ptr()
		}
	}
}//}}}
// Segtree implementation {{{
#[allow(dead_code)]
mod i1 {
	use crate::lazy_segtree::*;
	pub type V = i64;
	pub type L = i64;
	pub type R = i64;
	pub struct I;
	impl LSTNode for I {
		type V = V; type L = L; type R = R;
		fn def_value() -> Self::V {
			0
		}
		fn extract_result(res: &Self::V) -> Self::R {
			*res
		}
		fn combine_values(a: &Self::V, b: &Self::V) -> Self::V {
			*a.max(b)
		}
		fn reverse_value(_res: &Self::V) -> Self::V {
			panic!("bruh")
		}
		fn update_value_from_lazy(n: &mut N<Self>) {
			if let Some(l) = n.l {
				max!(n.v, l);
			}
		}
		fn augment_lazy(n: &mut N<Self>, l: &Self::L, _fw: bool) {
			if n.l.is_none() {
				n.l.replace(0);
			}
			let x = n.l.as_mut().unwrap();
			max!(*x, *l);
		}
		fn change_lazy_from_node(_n: &N<Self>, _l: &mut Self::L, _fw: bool) {
			// nothing
		}
	}
	impl I {
		pub fn def_value() -> V { <Self as LSTNode>::def_value() }
		pub fn extract_result(res: &V) -> R { <Self as LSTNode>::extract_result(res) }
		pub fn combine_values(a: &V, b: &V) -> V { <Self as LSTNode>::combine_values(a,b) }
		pub fn reverse_value(res: &V) -> V { <Self as LSTNode>::reverse_value(res) }
	}
}
pub type LST1 = lazy_segtree::LST<i1::I>;
//}}}

// Coordinate compression {{{
fn compress<T: Ord>(a: &[T], start_from: usize) -> (usize, Vec<usize>) {
	let n = a.len();
	let mut t = Vec::with_capacity(n);
	for i in 0..n {
		t.push(i);
	}
	t.sort_by(|x,y| a[*x].cmp(&a[*y]));
	let mut b = vec![0; n];
	let mut v = start_from;
	for i in 0..n {
		if i > 0 && a[t[i-1]] < a[t[i]] {
			v += 1;
		}
		b[t[i]] = v;
	}
	(v, b)
}//}}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	let n = rin.u();
	let mut s = v!([n]);
	rep!{[n]
		l!(a,b,h = rin.l());
		s.push( (b,a,h) );
	}
	s.sort();
	s.reverse();
	let mut ss = v!([n*2]);
	for &(b,a,_) in s.iter() {
		ss.push(a);
		ss.push(b);
	}
	let (m,ss) = compress(&ss,0);
	let mut st = LST1::new();
	st.init_def(m+1);
	for i in 0..n {
		let (a,b) = (ss[i+i], ss[i+i+1]);
		let mut res = s[i].2 + st.query(a,b);
		st.update(a,b,&mut res,true);
	}
	let sol = st.query(0,m);
	writeln!(rout, "{}", sol).ok();
}


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! min {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b < *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! max {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b > *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: v!([]), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = v!([8]);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn vvb(&mut self, r: usize, c: Option<usize>) -> Vec<Vec<u8>> {
		let mut res = v!([r]);
		let c = c.unwrap_or(0);
		rep!{[r]
			let t = self.vb();
			assert!(c == 0 || t.len() == c);
			res.push(t);
		}
		res
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
	fn graph(&mut self, n: usize, m: usize) -> Vec<Vec<usize>> {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); e[a].push(b); e[b].push(a); } e
	}
	fn graph_w<T: Copy+FromStr>(&mut self, n: usize, m: usize) -> Vec<Vec<(usize,T)>> where T::Err: Debug {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); let c: T = self.p(); e[a].push((b,c)); e[b].push((a,c)); } e
	}
}
//------------------- End rusT }}}

// Segtree base {{{
#[allow(dead_code)]
mod lazy_segtree
{
	pub struct Node<V,L> { pub v: V, pub l: Option<L>, pub b: B, pub ch: CH<Self> }
	impl<V,L> Node<V,L> {
		pub fn new(v: V, b: B) -> Self { Node { v, l: None, b, ch: None } }
		pub fn is_leaf(&self) -> bool { self.ch.is_none() }
		pub fn is_up_to_date(&self) -> bool { self.l.is_none() }
		pub fn len(&self) -> usize { self.b.1 - self.b.0 + 1 }
	}
	pub type B = (usize, usize);
	pub type CH<T> = Option<(*mut T, *mut T)>;
	pub type N<T> = Node<<T as LSTNode>::V,<T as LSTNode>::L>;
	pub trait LSTNode {
		type V: Clone; type L: Clone; type R;
		fn accum_result(res: &mut Self::V, v: &Self::V) {
			*res = Self::combine_values(res, v);
		}
		fn update_parent_value(n: &mut N<Self>) {
			assert!(n.ch.is_some());
			let (lc,rc) = n.ch.unwrap();
			n.v = Self::combine_values(unsafe {&(*lc).v}, unsafe {&(*rc).v});
		}
		fn build_parent_value(n: &mut N<Self>) {
			Self::update_parent_value(n);
		}
		fn update_lazy(n: &mut N<Self>, l: &mut Self::L, fw: bool) {
			Self::augment_lazy(n, l, fw);
			Self::change_lazy_from_node(n, l, fw);
		}
		fn update_children_lazy(n: &mut N<Self>) {
			assert!(n.ch.is_some());
			let (lc,rc) = n.ch.unwrap();
			if let Some(mut l) = n.l.take() {
				Self::update_lazy(unsafe {&mut*lc}, &mut l, true);
				Self::update_lazy(unsafe {&mut*rc}, &mut l, true);
			}
		}
		fn def_value() -> Self::V;
		fn extract_result(res: &Self::V) -> Self::R;
		fn combine_values(_: &Self::V, _: &Self::V) -> Self::V;
		fn reverse_value(_: &Self::V) -> Self::V;
		fn update_value_from_lazy(_: &mut N<Self>);
		fn change_lazy_from_node(_: &N<Self>, _: &mut Self::L, _: bool);
		fn augment_lazy(_: &mut N<Self>, _: &Self::L, _: bool);
	}
	struct UpInfo<'a,L> { l: usize, r: usize, lz: &'a mut L }
	struct QuInfo<V> { l: usize, r: usize, res: V }
	pub struct LST<T: LSTNode> { nodes: Vec<N<T>>, size: usize }
	impl<T: LSTNode> LST<T> {
		pub fn new() -> Self {
			Self { nodes: Vec::new(), size: 0 }
		}
		pub fn init_def(&mut self, s: usize) {
			self.init(vec![T::def_value(); s]);
		}
		pub fn init(&mut self, vals: Vec<T::V>) {
			self.size = vals.len(); self.nodes.clear();
			if self.size > 0 { self.init_nodes(vals); }
		}
		pub fn update(&mut self, l: usize, r: usize, lz: &mut T::L, fw: bool) {
			assert!(l <= r && r < self.size);
			Self::internal_update(unsafe {&mut*self.root()}, &mut UpInfo {l,r,lz}, fw);
		}
		pub fn query_val(&mut self, l: usize, r: usize) -> T::V {
			assert!(l <= r && r < self.size);
			let mut x = QuInfo { l, r, res: T::def_value() };
			Self::internal_query(unsafe {&mut*self.root()}, &mut x);
			x.res
		}
		pub fn query(&mut self, l: usize, r: usize) -> T::R {
			T::extract_result(&self.query_val(l,r))
		}
		fn seg_push(n: &mut N<T>) {
			if !n.is_up_to_date() {
				T::update_value_from_lazy(n);
				if n.ch.is_some() {
					T::update_children_lazy(n);
				}
				n.l = None;
			}
		}
		fn seg_merge(n: &mut N<T>) {
			if let Some((lc,rc)) = n.ch {
				Self::seg_push(unsafe {&mut*lc});
				Self::seg_push(unsafe {&mut*rc});
				T::update_parent_value(n);
			}
		}
		fn internal_update(n: &mut N<T>, x: &mut UpInfo<T::L>, fw: bool) {
			if x.l <= n.b.0 && n.b.1 <= x.r {
				T::update_lazy(n, &mut x.lz, fw);
				Self::seg_push(n);
			} else if x.l <= n.b.1 && n.b.0 <= x.r {
				Self::seg_push(n);
				let (lc,rc) = n.ch.unwrap();
				let (c0,c1) = if fw {(lc,rc)} else {(rc,lc)};
				Self::internal_update(unsafe {&mut*c0}, x, fw);
				Self::internal_update(unsafe {&mut*c1}, x, fw);
				Self::seg_merge(n);
			}
		}
		fn internal_query(n: &mut N<T>, x: &mut QuInfo<T::V>) {
			if x.l <= n.b.0 && n.b.1 <= x.r {
				Self::seg_push(n);
				T::accum_result(&mut x.res, &n.v);
			} else if x.l <= n.b.1 && n.b.0 <= x.r {
				let (lc,rc) = n.ch.unwrap();
				Self::seg_push(n);
				Self::internal_query(unsafe {&mut*lc}, x);
				Self::internal_query(unsafe {&mut*rc}, x);
				Self::seg_merge(n);
			}
		}
		fn init_nodes(&mut self, vals: Vec<T::V>) {
			let sz = 2 * self.size - 1;
			self.nodes.reserve(sz);
			let mut q = Vec::new();
			q.push((0, self.size - 1));
			while let Some((l,r)) = q.pop() {
				if l == r {
					let v = vals[l].clone();
					self.nodes.push(N::<T>::new(v, (l,r)));
				} else {
					let m = l + (r - l + 1) / 2;
					q.push((m, r));
					q.push((l, m - 1));
					let id = self.nodes.len();
					let v = T::def_value();
					let p = self.nodes.as_mut_ptr();
					let lc = unsafe { p.add(id + 1) };
					let rc = unsafe { p.add(id + 2 * (m - l)) };
					self.nodes.push(N::<T> { v, l: None, b: (l,r), ch: Some((lc,rc)) });
				}
			}
			assert_eq!(self.nodes.len(), sz);
			for n in self.nodes.iter_mut().rev() {
				if !n.is_leaf() {
					T::build_parent_value(n);
				}
			}
		}
		fn root(&mut self) -> *mut N<T> {
			assert!(!self.nodes.is_empty());
			self.nodes.as_mut_ptr()
		}
	}
}//}}}
// Segtree implementation {{{
#[allow(dead_code)]
mod i1 {
	use crate::lazy_segtree::*;
	pub type V = i64;
	pub type L = i64;
	pub type R = i64;
	pub struct I;
	impl LSTNode for I {
		type V = V; type L = L; type R = R;
		fn def_value() -> Self::V {
			0
		}
		fn extract_result(res: &Self::V) -> Self::R {
			*res
		}
		fn combine_values(a: &Self::V, b: &Self::V) -> Self::V {
			*a.max(b)
		}
		fn reverse_value(_res: &Self::V) -> Self::V {
			panic!("bruh")
		}
		fn update_value_from_lazy(n: &mut N<Self>) {
			if let Some(l) = n.l {
				max!(n.v, l);
			}
		}
		fn augment_lazy(n: &mut N<Self>, l: &Self::L, _fw: bool) {
			if n.l.is_none() {
				n.l.replace(0);
			}
			let x = n.l.as_mut().unwrap();
			max!(*x, *l);
		}
		fn change_lazy_from_node(_n: &N<Self>, _l: &mut Self::L, _fw: bool) {
			// nothing
		}
	}
	impl I {
		pub fn def_value() -> V { <Self as LSTNode>::def_value() }
		pub fn extract_result(res: &V) -> R { <Self as LSTNode>::extract_result(res) }
		pub fn combine_values(a: &V, b: &V) -> V { <Self as LSTNode>::combine_values(a,b) }
		pub fn reverse_value(res: &V) -> V { <Self as LSTNode>::reverse_value(res) }
	}
}
pub type LST1 = lazy_segtree::LST<i1::I>;
//}}}

// Coordinate compression {{{
fn compress<T: Ord>(a: &[T], start_from: usize) -> (usize, Vec<usize>) {
	let n = a.len();
	let mut t = Vec::with_capacity(n);
	for i in 0..n {
		t.push(i);
	}
	t.sort_by(|x,y| a[*x].cmp(&a[*y]));
	let mut b = vec![0; n];
	let mut v = start_from;
	for i in 0..n {
		if i > 0 && a[t[i-1]] < a[t[i]] {
			v += 1;
		}
		b[t[i]] = v;
	}
	(v, b)
}//}}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	let n = rin.u();
	let mut s = v!([n]);
	rep!{[n]
		l!(a,b,h = rin.l());
		s.push( (-b,a,h) );
	}
	s.sort();
	let mut ss = v!([n*2]);
	for &(b,a,_) in s.iter() {
		ss.push(a);
		ss.push(-b);
	}
	let (m,ss) = compress(&ss,0);
	let mut st = LST1::new();
	st.init_def(m+1);
	for i in 0..n {
		let (a,b) = (ss[i+i], ss[i+i+1]);
		let mut res = s[i].2 + st.query(a,b);
		st.update(a,b,&mut res,true);
	}
	let sol = st.query(0,m);
	writeln!(rout, "{}", sol).ok();
}


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! min {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b < *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! max {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b > *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: v!([]), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = v!([8]);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn vvb(&mut self, r: usize, c: Option<usize>) -> Vec<Vec<u8>> {
		let mut res = v!([r]);
		let c = c.unwrap_or(0);
		rep!{[r]
			let t = self.vb();
			assert!(c == 0 || t.len() == c);
			res.push(t);
		}
		res
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
	fn graph(&mut self, n: usize, m: usize) -> Vec<Vec<usize>> {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); e[a].push(b); e[b].push(a); } e
	}
	fn graph_w<T: Copy+FromStr>(&mut self, n: usize, m: usize) -> Vec<Vec<(usize,T)>> where T::Err: Debug {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); let c: T = self.p(); e[a].push((b,c)); e[b].push((a,c)); } e
	}
}
//------------------- End rusT }}}

// Segtree base {{{
#[allow(dead_code)]
mod lazy_segtree
{
	pub struct Node<V,L> { pub v: V, pub l: Option<L>, pub b: B, pub ch: CH<Self> }
	impl<V,L> Node<V,L> {
		pub fn new(v: V, b: B) -> Self { Node { v, l: None, b, ch: None } }
		pub fn is_leaf(&self) -> bool { self.ch.is_none() }
		pub fn is_up_to_date(&self) -> bool { self.l.is_none() }
		pub fn len(&self) -> usize { self.b.1 - self.b.0 + 1 }
	}
	pub type B = (usize, usize);
	pub type CH<T> = Option<(*mut T, *mut T)>;
	pub type N<T> = Node<<T as LSTNode>::V,<T as LSTNode>::L>;
	pub trait LSTNode {
		type V: Clone; type L: Clone; type R;
		fn accum_result(res: &mut Self::V, v: &Self::V) {
			*res = Self::combine_values(res, v);
		}
		fn update_parent_value(n: &mut N<Self>) {
			assert!(n.ch.is_some());
			let (lc,rc) = n.ch.unwrap();
			n.v = Self::combine_values(unsafe {&(*lc).v}, unsafe {&(*rc).v});
		}
		fn build_parent_value(n: &mut N<Self>) {
			Self::update_parent_value(n);
		}
		fn update_lazy(n: &mut N<Self>, l: &mut Self::L, fw: bool) {
			Self::augment_lazy(n, l, fw);
			Self::change_lazy_from_node(n, l, fw);
		}
		fn update_children_lazy(n: &mut N<Self>) {
			assert!(n.ch.is_some());
			let (lc,rc) = n.ch.unwrap();
			if let Some(mut l) = n.l.take() {
				Self::update_lazy(unsafe {&mut*lc}, &mut l, true);
				Self::update_lazy(unsafe {&mut*rc}, &mut l, true);
			}
		}
		fn def_value() -> Self::V;
		fn extract_result(res: &Self::V) -> Self::R;
		fn combine_values(_: &Self::V, _: &Self::V) -> Self::V;
		fn reverse_value(_: &Self::V) -> Self::V;
		fn update_value_from_lazy(_: &mut N<Self>);
		fn change_lazy_from_node(_: &N<Self>, _: &mut Self::L, _: bool);
		fn augment_lazy(_: &mut N<Self>, _: &Self::L, _: bool);
	}
	struct UpInfo<'a,L> { l: usize, r: usize, lz: &'a mut L }
	struct QuInfo<V> { l: usize, r: usize, res: V }
	pub struct LST<T: LSTNode> { nodes: Vec<N<T>>, size: usize }
	impl<T: LSTNode> LST<T> {
		pub fn new() -> Self {
			Self { nodes: Vec::new(), size: 0 }
		}
		pub fn init_def(&mut self, s: usize) {
			self.init(vec![T::def_value(); s]);
		}
		pub fn init(&mut self, vals: Vec<T::V>) {
			self.size = vals.len(); self.nodes.clear();
			if self.size > 0 { self.init_nodes(vals); }
		}
		pub fn update(&mut self, l: usize, r: usize, lz: &mut T::L, fw: bool) {
			assert!(l <= r && r < self.size);
			Self::internal_update(unsafe {&mut*self.root()}, &mut UpInfo {l,r,lz}, fw);
		}
		pub fn query_val(&mut self, l: usize, r: usize) -> T::V {
			assert!(l <= r && r < self.size);
			let mut x = QuInfo { l, r, res: T::def_value() };
			Self::internal_query(unsafe {&mut*self.root()}, &mut x);
			x.res
		}
		pub fn query(&mut self, l: usize, r: usize) -> T::R {
			T::extract_result(&self.query_val(l,r))
		}
		fn seg_push(n: &mut N<T>) {
			if !n.is_up_to_date() {
				T::update_value_from_lazy(n);
				if n.ch.is_some() {
					T::update_children_lazy(n);
				}
				n.l = None;
			}
		}
		fn seg_merge(n: &mut N<T>) {
			if let Some((lc,rc)) = n.ch {
				Self::seg_push(unsafe {&mut*lc});
				Self::seg_push(unsafe {&mut*rc});
				T::update_parent_value(n);
			}
		}
		fn internal_update(n: &mut N<T>, x: &mut UpInfo<T::L>, fw: bool) {
			if x.l <= n.b.0 && n.b.1 <= x.r {
				T::update_lazy(n, &mut x.lz, fw);
				Self::seg_push(n);
			} else if x.l <= n.b.1 && n.b.0 <= x.r {
				Self::seg_push(n);
				let (lc,rc) = n.ch.unwrap();
				let (c0,c1) = if fw {(lc,rc)} else {(rc,lc)};
				Self::internal_update(unsafe {&mut*c0}, x, fw);
				Self::internal_update(unsafe {&mut*c1}, x, fw);
				Self::seg_merge(n);
			}
		}
		fn internal_query(n: &mut N<T>, x: &mut QuInfo<T::V>) {
			if x.l <= n.b.0 && n.b.1 <= x.r {
				Self::seg_push(n);
				T::accum_result(&mut x.res, &n.v);
			} else if x.l <= n.b.1 && n.b.0 <= x.r {
				let (lc,rc) = n.ch.unwrap();
				Self::seg_push(n);
				Self::internal_query(unsafe {&mut*lc}, x);
				Self::internal_query(unsafe {&mut*rc}, x);
				Self::seg_merge(n);
			}
		}
		fn init_nodes(&mut self, vals: Vec<T::V>) {
			let sz = 2 * self.size - 1;
			self.nodes.reserve(sz);
			let mut q = Vec::new();
			q.push((0, self.size - 1));
			while let Some((l,r)) = q.pop() {
				if l == r {
					let v = vals[l].clone();
					self.nodes.push(N::<T>::new(v, (l,r)));
				} else {
					let m = l + (r - l + 1) / 2;
					q.push((m, r));
					q.push((l, m - 1));
					let id = self.nodes.len();
					let v = T::def_value();
					let p = self.nodes.as_mut_ptr();
					let lc = unsafe { p.add(id + 1) };
					let rc = unsafe { p.add(id + 2 * (m - l)) };
					self.nodes.push(N::<T> { v, l: None, b: (l,r), ch: Some((lc,rc)) });
				}
			}
			assert_eq!(self.nodes.len(), sz);
			for n in self.nodes.iter_mut().rev() {
				if !n.is_leaf() {
					T::build_parent_value(n);
				}
			}
		}
		fn root(&mut self) -> *mut N<T> {
			assert!(!self.nodes.is_empty());
			self.nodes.as_mut_ptr()
		}
	}
}//}}}
// Segtree implementation {{{
#[allow(dead_code)]
mod i1 {
	use crate::lazy_segtree::*;
	pub type V = i64;
	pub type L = i64;
	pub type R = i64;
	pub struct I;
	impl LSTNode for I {
		type V = V; type L = L; type R = R;
		fn def_value() -> Self::V {
			0
		}
		fn extract_result(res: &Self::V) -> Self::R {
			*res
		}
		fn combine_values(a: &Self::V, b: &Self::V) -> Self::V {
			*a.max(b)
		}
		fn reverse_value(_res: &Self::V) -> Self::V {
			panic!("bruh")
		}
		fn update_value_from_lazy(n: &mut N<Self>) {
			if let Some(l) = n.l {
				max!(n.v, l);
			}
		}
		fn augment_lazy(n: &mut N<Self>, l: &Self::L, _fw: bool) {
			if n.l.is_none() {
				n.l.replace(0);
			}
			let x = n.l.as_mut().unwrap();
			max!(*x, *l);
		}
		fn change_lazy_from_node(_n: &N<Self>, _l: &mut Self::L, _fw: bool) {
			// nothing
		}
	}
	impl I {
		pub fn def_value() -> V { <Self as LSTNode>::def_value() }
		pub fn extract_result(res: &V) -> R { <Self as LSTNode>::extract_result(res) }
		pub fn combine_values(a: &V, b: &V) -> V { <Self as LSTNode>::combine_values(a,b) }
		pub fn reverse_value(res: &V) -> V { <Self as LSTNode>::reverse_value(res) }
	}
}
pub type LST1 = lazy_segtree::LST<i1::I>;
//}}}

// Coordinate compression {{{
fn compress<T: Ord>(a: &[T], start_from: usize) -> (usize, Vec<usize>) {
	let n = a.len();
	let mut t = Vec::with_capacity(n);
	for i in 0..n {
		t.push(i);
	}
	t.sort_by(|x,y| a[*x].cmp(&a[*y]));
	let mut b = vec![0; n];
	let mut v = start_from;
	for i in 0..n {
		if i > 0 && a[t[i-1]] < a[t[i]] {
			v += 1;
		}
		b[t[i]] = v;
	}
	(v, b)
}//}}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	let n = rin.u();
	let mut s = v!([n]);
	rep!{[n]
		l!(a,b,h = rin.l());
		s.push( (b,a+1,h) );
	}
	s.sort();
	s.reverse();
	let mut ss = v!([n*2]);
	for &(b,a,_) in s.iter() {
		ss.push(a);
		ss.push(b);
	}
	let (m,ss) = compress(&ss,0);
	let mut st = LST1::new();
	st.init_def(m+1);
	for i in 0..n {
		let (a,b) = (ss[i+i], ss[i+i+1]);
		let mut res = s[i].2 + st.query(a,b);
		st.update(a,b,&mut res,true);
	}
	let sol = st.query(0,m);
	writeln!(rout, "{}", sol).ok();
}


import sys

raw_input = sys.stdin.readline
n = input()
disks = []
stack = []
ans = [0]*n

for i in xrange(n):
    inner, outer, height = map(int, raw_input().split())
    disks.append((inner, outer, height))

disks.sort(key = lambda x: x[1])
for i in xrange(n-1, -1, -1):
    inner, outer, h = disks[i]
    if i == n-1:
        ans[i] = h
        stack.append((inner, i))
    else:
        prev_inner, index = stack[-1]
        while outer <= prev_inner and stack:
            stack.pop()
            if stack:
                prev_inner, index = stack[-1]

        if stack:
            ans[i] = h + ans[index]
        else:
            ans[i] = h

        stack.append((inner, i))

print max(ans)


import sys

raw_input = sys.stdin.readline
n = input()
disks = []
stack = []
ans = [0]*n

for i in xrange(n):
    inner, outer, height = map(int, raw_input().split())
    disks.append((inner, outer, height))

disks.sort(key = lambda x: (x[1], x[0]))
for i in xrange(n-1, -1, -1):
    inner, outer, h = disks[i]
    if i == n-1:
        ans[i] = h
        stack.append((inner, i))
    else:
        prev_inner, index = stack[-1]
        while outer <= prev_inner and stack:
            stack.pop()
            if stack:
                prev_inner, index = stack[-1]

        ans[i] = h
        if stack:
            ans[i] += ans[index]

        stack.append((inner, i))

print max(ans)


#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <fstream>
#include <string>
#include <stack>
#include <deque>
#include <algorithm>
#include <random>
#include <ctime>
#include <sstream>
#include <list>
#include <functional>
#include <numeric>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define sq(x) ((x)*(x))
#define bcount(x) __builtin_popcount(x)
//#define gcd(x,y) __gcd(x,y)

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
const double PI = atan(1.0) * 4;

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.precision(20);
	//freopen("unequal.in", "r", stdin);
	//freopen("unequal.out", "w", stdout);

	int n;
	cin >> n;
	vector<string> v(n);
	vint vk(n);

	for (auto& x : v)
		cin >> x;

	vector<pii> start, end;

	for (int i = 0; i < n; i++)
	{
		auto x = v[i];
		int k = 0;
		bool wasm = false;
		for (auto& y : x)
		{
			if (y == '(')
				k++;
			else
			{
				k--;
				if (k < 0)
					wasm = true;
			}
		}

		if (wasm && k >= 0) continue;

		if (wasm)
		{
			if (x.back() == ')')
				end.push_back({ i,k });
		}
		else
		{
			if (x.back() == ')')
				end.push_back({ i,k });
			if (x[0] == '(')
				start.push_back({ i, k });
		}
	}
	ll ans = 0;
	for (auto& i : start)
	{
		for (auto& j : end)
		{
			if (i.second + j.second == 0) ans++;
			/*string s = v[i.first] + v[j.first];
			int k = 0;
			for (auto& x : s)
			{
				if (x == '(')
					k++;
				else
				{
					k--;
					if (k < 0)
						break;
				}
			}
			if (k == 0)
				ans++;*/
		}
	}
	cout << ans;
}


#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <fstream>
#include <string>
#include <stack>
#include <deque>
#include <algorithm>
#include <random>
#include <ctime>
#include <sstream>
#include <list>
#include <functional>
#include <numeric>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define sq(x) ((x)*(x))
#define bcount(x) __builtin_popcount(x)
//#define gcd(x,y) __gcd(x,y)

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
const double PI = atan(1.0) * 4;

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.precision(20);
	//freopen("unequal.in", "r", stdin);
	//freopen("unequal.out", "w", stdout);

	int n;
	cin >> n;
	vector<string> v(n);
	vint vk(n);

	for (auto& x : v)
		cin >> x;

	//vector<pii> start, end;
	map<int, int> start, end;
	for (int i = 0; i < n; i++)
	{
		auto x = v[i];
		int k = 0;
		bool wasm = false;
		for (auto& y : x)
		{
			if (y == '(')
				k++;
			else
			{
				k--;
				if (k < 0)
					wasm = true;
			}
		}

		if (wasm && k >= 0) continue;

		if (wasm)
		{
			if (x.back() == ')')
				end[k]++;
			//end.push_back({ i,k });
		}
		else
		{
			if (k == 0 && x.back() == ')')
				end[k]++;
			//end.push_back({ i,k });
			if (x[0] == '(')
				start[k]++;
			//start.push_back({ i, k });
		}
	}
	ll ans = 0;
	for (auto& i : start)
	{
		ans += i.second* end[-i.first];
		//for (auto& j : end)
		//{
		//	if (i.second + j.second == 0) ans++;
		//	/*string s = v[i.first] + v[j.first];
		//	int k = 0;
		//	for (auto& x : s)
		//	{
		//		if (x == '(')
		//			k++;
		//		else
		//		{
		//			k--;
		//			if (k < 0)
		//				break;
		//		}
		//	}
		//	if (k == 0)
		//		ans++;*/
		//}
	}
	cout << ans;
}


#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <fstream>
#include <string>
#include <stack>
#include <deque>
#include <algorithm>
#include <random>
#include <ctime>
#include <sstream>
#include <list>
#include <functional>
#include <numeric>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define sq(x) ((x)*(x))
#define bcount(x) __builtin_popcount(x)
//#define gcd(x,y) __gcd(x,y)

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
const double PI = atan(1.0) * 4;

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.precision(20);
	//freopen("unequal.in", "r", stdin);
	//freopen("unequal.out", "w", stdout);

	int n;
	cin >> n;
	vector<string> v(n);
	vint vk(n);

	for (auto& x : v)
		cin >> x;

	//vector<pii> start, end;
	map<int, int> start, end;
	ll ans = 0;
	for (int i = 0; i < n; i++)
	{
		auto x = v[i];
		int open = 0, close = 0;
		for (auto& y : x)
		{
			if (y == '(')
				open++;
			else
			{
				if (open != 0)
					open--;
				else
					close++;
			}
		}
		if (close != 0 && open != 0) continue;
		if (close == 0 && open == 0)
		{
			start[open]++;
			end[close]++;
		}
		else if (close != 0)
			end[close]++;
		else
			start[open]++;
	}
	for (auto& i : start)
	{
		ans += i.second* end[i.first];
	}
	cout << ans;
}


#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <fstream>
#include <string>
#include <stack>
#include <deque>
#include <algorithm>
#include <random>
#include <ctime>
#include <sstream>
#include <list>
#include <functional>
#include <numeric>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define sq(x) ((x)*(x))
#define bcount(x) __builtin_popcount(x)
//#define gcd(x,y) __gcd(x,y)

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
const double PI = atan(1.0) * 4;

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.precision(20);
	//freopen("unequal.in", "r", stdin);
	//freopen("unequal.out", "w", stdout);

	int n;
	cin >> n;
	vector<string> v(n);
	vll vk(n);

	for (auto& x : v)
		cin >> x;

	vll start, end;

	for (int i = 0; i < n; i++)
	{
		auto x = v[i];
		if (x[0] == '(')
			start.push_back(i);
		if (x.back() == ')')
			end.push_back(i);
		ll k = 0;
		for (auto& y : x)
		{
			if (y == '(')
				k++;
			else
				k--;
		}
		vk[i] = k;
	}
	vll partk(n), rpartk(n);
	partial_sum(all(vk), partk.begin());
	partial_sum(rall(vk), rpartk.begin());
	ll ans = 0;
	for (auto& x : start)
	{
		for (auto& y : end)
		{
			if (x < y)
			{
				if (x == 0)
				{
					if (partk[y] == 0)
						ans++;
				}
				else if (partk[y] - partk[x - 1] == 0)
					ans++;
			}
			else
			{
				if (y == 0)
				{
					if (rpartk[x] == 0)
						ans++;
				}
				else if (rpartk[x] - rpartk[y - 1] == 0)
					ans++;
			}
		}
	}
	cout << ans;
}


#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <fstream>
#include <string>
#include <stack>
#include <deque>
#include <algorithm>
#include <random>
#include <ctime>
#include <sstream>
#include <list>
#include <functional>
#include <numeric>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define sq(x) ((x)*(x))
#define bcount(x) __builtin_popcount(x)
//#define gcd(x,y) __gcd(x,y)

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
const double PI = atan(1.0) * 4;

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.precision(20);
	//freopen("unequal.in", "r", stdin);
	//freopen("unequal.out", "w", stdout);

	int n;
	cin >> n;
	vector<string> v(n);
	vint vk(n);

	for (auto& x : v)
		cin >> x;

	//vector<pii> start, end;
	map<ll, ll> start, end;
	ll ans = 0;
	for (int i = 0; i < n; i++)
	{
		auto x = v[i];
		int open = 0, close = 0;
		for (auto& y : x)
		{
			if (y == '(')
				open++;
			else
			{
				if (open > 0)
					open--;
				else
					close++;
			}
		}
		if (close != 0 && open != 0) continue;
		if (close == 0 && open == 0)
		{
			start[open]++;
			end[close]++;
		}
		else if (close != 0)
			end[close]++;
		else
			start[open]++;
	}
	for (auto& i : start)
	{
		ans += i.second* end[i.first];
	}
	cout << ans;
}


#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <fstream>
#include <string>
#include <stack>
#include <deque>
#include <algorithm>
#include <random>
#include <ctime>
#include <sstream>
#include <list>
#include <functional>
#include <numeric>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define sq(x) ((x)*(x))
#define bcount(x) __builtin_popcount(x)
//#define gcd(x,y) __gcd(x,y)

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
const double PI = atan(1.0) * 4;

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.precision(20);
	//freopen("unequal.in", "r", stdin);
	//freopen("unequal.out", "w", stdout);

	int n;
	cin >> n;
	vector<string> v(n);
	vint vk(n);

	for (auto& x : v)
		cin >> x;

	vint start, end;

	for (int i = 0; i < n; i++)
	{
		auto x = v[i];
		int k = 0;
		for (auto& y : x)
		{
			if (y == '(')
				k++;
			else
			{
				k--;
				if (k < 0)
					break;
			}
		}

		if (x.back() == ')' && k <= 0)
			end.push_back(i);
		if (x[0] == '(' && k >= 0)
			start.push_back(i);
	}
	ll ans = 0;
	for (auto& i: start)
	{
		for (auto& j : end)
		{
			string s = v[i] + v[j];
			int k = 0;
			for (auto& x :s)
			{
				if (x == '(')
					k++;
				else
				{
					k--;
					if (k < 0)
						break;
				}
			}
			if (k == 0)
				ans++;
		}
	}
	cout << ans;
}


#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <fstream>
#include <string>
#include <stack>
#include <deque>
#include <algorithm>
#include <random>
#include <ctime>
#include <sstream>
#include <list>
#include <functional>
#include <numeric>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define sq(x) ((x)*(x))
#define bcount(x) __builtin_popcount(x)
//#define gcd(x,y) __gcd(x,y)

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
const double PI = atan(1.0) * 4;

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.precision(20);
	//freopen("unequal.in", "r", stdin);
	//freopen("unequal.out", "w", stdout);

	int n;
	cin >> n;
	vector<string> v(n);
	vint vk(n);

	for (auto& x : v)
		cin >> x;

	vint start, end;

	for (int i = 0; i < n; i++)
	{
		auto x = v[i];
		if (x[0] == '(')
			start.push_back(i);
		if (x.back() == ')')
			end.push_back(i);
		int k = 0;
		for (auto& y : x)
		{
			if (y == '(')
				k++;
			else
				k--;
		}
		vk[i] = k;
	}
	vint partk(n), rpartk(n);
	partial_sum(all(vk), partk.begin());
	partial_sum(rall(vk), rpartk.begin());
	ll ans = 0;
	for (auto& x : start)
	{
		for (auto& y : end)
		{
			if (x < y)
			{
				if (x == 0)
				{
					if (partk[y] == 0)
						ans++;
				}
				else if (partk[y] - partk[x - 1] == 0)
					ans++;
			}
			else
			{
				if (y == 0)
				{
					if (rpartk[x] == 0)
						ans++;
				}
				else if (rpartk[x] - rpartk[y - 1] == 0)
					ans++;
			}
		}
	}
	cout << ans;
}


#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <fstream>
#include <string>
#include <stack>
#include <deque>
#include <algorithm>
#include <random>
#include <ctime>
#include <sstream>
#include <list>
#include <functional>
#include <numeric>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define sq(x) ((x)*(x))
#define bcount(x) __builtin_popcount(x)
//#define gcd(x,y) __gcd(x,y)

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
const double PI = atan(1.0) * 4;

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.precision(20);
	//freopen("unequal.in", "r", stdin);
	//freopen("unequal.out", "w", stdout);

	int n;
	cin >> n;
	vector<string> v(n);
	vint vk(n);

	for (auto& x : v)
		cin >> x;

	//vector<pii> start, end;
	map<int, int> start, end;
	for (int i = 0; i < n; i++)
	{
		auto x = v[i];
		int k = 0;
		bool wasm = false;
		for (auto& y : x)
		{
			if (y == '(')
				k++;
			else
			{
				k--;
				if (k < 0)
					wasm = true;
			}
		}

		if (wasm && k >= 0) continue;

		if (wasm)
		{
			if (x.back() == ')' && k < 0)
				end[k]++;
			//end.push_back({ i,k });
		}
		else
		{
			if (k == 0 && x.back() == ')')
				end[k]++;
			//end.push_back({ i,k });
			if (x[0] == '(')
				start[k]++;
			//start.push_back({ i, k });
		}
	}
	ll ans = 0;
	for (auto& i : start)
	{
		ans += i.second* end[-i.first];
		//for (auto& j : end)
		//{
		//	if (i.second + j.second == 0) ans++;
		//	/*string s = v[i.first] + v[j.first];
		//	int k = 0;
		//	for (auto& x : s)
		//	{
		//		if (x == '(')
		//			k++;
		//		else
		//		{
		//			k--;
		//			if (k < 0)
		//				break;
		//		}
		//	}
		//	if (k == 0)
		//		ans++;*/
		//}
	}
	cout << ans;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define vec vector
#define pb push_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define Str(x) to_string(x)

using namespace std;
using ll = long long;
using ull = unsigned long long;
using str = string;

int main()
{
	ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
	int n;
	cin >> n;
	map<ll, ll> depths;
	ll ans = 0;
	for (int i = 0; i < n; ++i)
	{
		str s;
		cin >> s;
		ll depth = 0;
		bool ok = 1;
		for (int i = 0; s[i]; ++i)
		{
			depth += (s[i] == '(' ? 1 : -1);
			if (i && depth < 0 && s[i + 1])
			{
				ok = 0;
				break;
			}
		}
		if (depth == 0)
			++ans;
		else if (ok)
		{
			depths[depth]++;
		}
	}
	ans *= ans;
	for (auto &it : depths)
	{
		if (it.first > 0)
			break;
		ans += it.second * depths[-it.first];
	}
	cout << ans;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define vec vector
#define pb push_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define Str(x) to_string(x)
#define len(s) size(s)

using namespace std;
using ll = long long;
using ull = unsigned long long;
using str = string;

int main()
{
	ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
	int n;
	cin >> n;
	map<ll, ll> depths;
	ll ans = 0;
	for (int i = 0; i < n; ++i)
	{
		str s;
		cin >> s;
		ll depth = 0, rdepth = 0;
		bool ok = 1, rok = 1;
		for (int i = 0; (ok || rok) && s[i]; ++i)
		{
			depth += (s[i] == '(' ? 1 : -1);
			if (depth < 0)
				ok = 0;
			rdepth += (s[len(s) - 1 - i] == ')' ? 1 : -1);
			if (rdepth < 0)
				rok = 0;
		}
		if (ok || rok)
			depths[depth]++;
	}
	for (auto &it : depths)
	{
		if (it.first > 0)
			break;
		ans += it.second * depths[-it.first];
	}
	cout << ans;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define vec vector
#define pb push_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define Str(x) to_string(x)

using namespace std;
using ll = long long;
using ull = unsigned long long;
using str = string;

int main()
{
	ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
	int n;
	cin >> n;
	map<int, int> depths;
	int ans = 0;
	for (int i = 0; i < n; ++i)
	{
		str s;
		cin >> s;
		int depth = 0;
		bool ok = 1;
		for (int i = 0; s[i]; ++i)
		{
			depth += (s[i] == '(' ? 1 : -1);
			if (depth < 0 && s[i + 1])
			{
				ok = 0;
				break;
			}
		}
		if (depth == 0)
			++ans;
		else if (ok)
		{
			depths[depth]++;
		}
	}
	ans *= ans;
	for (auto &it : depths)
	{
		if (it.first > 0)
			break;
		ans += it.second * depths[-it.first];
	}
	cout << ans;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define vec vector
#define pb push_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define Str(x) to_string(x)

using namespace std;
using ll = long long;
using ull = unsigned long long;
using str = string;

int main()
{
	ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
	int n;
	cin >> n;
	map<ll, ll> depths;
	ll ans = 0;
	for (int i = 0; i < n; ++i)
	{
		str s;
		cin >> s;
		ll depth = 0;
		bool ok = 1;
		for (int i = 0; s[i]; ++i)
		{
			depth += (s[i] == '(' ? 1 : -1);
			if (depth < 0)
				ok = 0;
		}
		if (depth == 0)
		{
			if (!ok)
				continue;
			else
			{
				++ans;
			}
		}
		else
		{
			depths[depth]++;
		}
	}
	ans *= ans;
	for (auto &it : depths)
	{
		if (it.first > 0)
			break;
		ans += it.second * depths[-it.first];
	}
	cout << ans;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define vec vector
#define pb push_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define Str(x) to_string(x)

using namespace std;
using ll = long long;
using ull = unsigned long long;
using str = string;

int main()
{
	ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
	int n;
	cin >> n;
	vec<int> depths;
	for (int i = 0; i < n; ++i)
	{
		str s;
		cin >> s;
		int depth = 0;
		bool ok = 1;
		for (int i = 0; s[i]; ++i)
		{
			depth += (s[i] == '(' ? 1 : -1);
			if (depth < 0 && s[i + 1])
			{
				ok = 0;
				break;
			}
		}
		if (ok)
		{
			depths.pb(depth);
		}
	}
	sort(all(depths));
	int ans = 0;
	n = size(depths);
	int l = 0, r = n - 1;
	while (l < r)
	{
		int m = l + r >> 1;
		if (depths[m] < 0)
			l = m + 1;
		else
			r = m;
	}
	if (depths[l] < 0)
	{
		cout << 0;
		return 0;
	}
	for (int i = l; i < n; ++i)
	{
		int l = 0, r = i;
		while (l < r)
		{
			int m = l + r >> 1;
			if (depths[m] < -depths[i])
				l = m + 1;
			else
				r = m;
		}
		for (int j = l; j < n && depths[j] == -depths[i]; ++j)
		{
			++ans;
		}
	}
	cout << ans;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define vec vector
#define pb push_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define Str(x) to_string(x)

using namespace std;
using ll = long long;
using ull = unsigned long long;
using str = string;

int main()
{
	ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
	int n;
	cin >> n;
	map<ll, ll> depths;
	ll ans = 0;
	for (int i = 0; i < n; ++i)
	{
		str s;
		cin >> s;
		ll depth = 0;
		bool ok = 1;
		for (int i = 0; s[i]; ++i)
		{
			depth += (s[i] == '(' ? 1 : -1);
			if (depth < 0 && s[i + 1])
			{
				ok = 0;
				break;
			}
		}
		if (depth == 0)
			++ans;
		else if (ok)
		{
			depths[depth]++;
		}
	}
	ans *= ans;
	for (auto &it : depths)
	{
		if (it.first > 0)
			break;
		ans += it.second * depths[-it.first];
	}
	cout << ans;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define vec vector
#define pb push_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define Str(x) to_string(x)

using namespace std;
using ll = long long;
using ull = unsigned long long;
using str = string;

int main()
{
	ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
	int n;
	cin >> n;
	map<ll, ll> depths;
	ll ans = 0;
	for (int i = 0; i < n; ++i)
	{
		str s;
		cin >> s;
		ll depth = 0;
		bool ok = 1;
		for (int i = 0; s[i]; ++i)
		{
			depth += (s[i] == '(' ? 1 : -1);
		}
		if (depth == 0)
			++ans;
		else
		{
			depths[depth]++;
		}
	}
	ans *= ans;
	for (auto &it : depths)
	{
		if (it.first > 0)
			break;
		ans += it.second * depths[-it.first];
	}
	cout << ans;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define vec vector
#define pb push_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define Str(x) to_string(x)

using namespace std;
using ll = long long;
using ull = unsigned long long;
using str = string;

int main()
{
	ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
	int n;
	cin >> n;
	vec<int> depths(n, 0);
	for (int i = 0; i < n; ++i)
	{
		str s;
		cin >> s;
		auto &depth = depths[i];
		for (auto &c : s)
		{
			depth += (c == '(' ? 1 : -1);
		}
	}
	int ans = 0;
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if (depths[i] >= depths[j] && depths[i] + depths[j] == 0)
			{
				++ans;
				//cout << i << ' ' << j << endl;
			}
		}
	}
	cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef vector<pii> vpii;
typedef vector<pil> vpil;
typedef vector<pli> vpli;
typedef set<int> si;
typedef set<ll> sll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

const double pi = acos(-1.0);
const long long INF = 2e18;

#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define sz size()
#define in insert
#define endl "\n"

#define sqr(a) ((a) * (a))
#define jor(a) !(a&1)// jor means EVEN number
#define bjor(a) (a&1)// bjor means ODD number

#define all(a)  a.begin(), a.end()
#define mem(arr, b) memset(arr, b, sizeof(arr)) //memset only for -1 and 0
//fill(a, a+n, 5) //fill for any value

#define for0(i,b) for(int i=0;i<(b);i++)
#define for1(i,b) for(int i=1;i<=(b);i++)
#define forab(i,a,b) for(int i=(a);i<=(b);i++)
#define forba(i,b,a) for(int i=(b);i>=(a);i--)
#define rep(i,a,b,c) for(int i=(a);i!=(b);i+=(c))

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define fileRead freopen("input.txt", "r", stdin);
#define fileWrite freopen("output.txt", "w", stdout);

void print(int a[], int n){ // for testing or debugging
    for(int i=0;i<n;i++)cout<<a[i]<<" "; cout<<endl;
}

//--------------------------------------------------------------------------

ll f(ll n){
    if(n==1) return 1;
    else {
        return n*(n+1) - n;
    }
}

int main()
{
    int n; cin>>n;
    //vector<string>L,R;
    map<int, int> L,R;
    si sett;
    for0(i,n) {
        string s; cin>>s;
        bool minus=0;
        int c=0;
        for(auto t:s){
            if(t=='(') c++;
            else{
                c--;
            }
            if(c==-1) minus=1;
        }
        if(minus and c==0) continue;
        else {
            if(c>=0) R[c]++;
            else L[c]++;
            sett.in(abs(c));
        }
    }
    ll ans=0;
    for(auto t:sett){
        int x = abs(t);
        if(x==0){
            ll y = R[t];
            ans+=f(y);
        }
        else ans+=1LL*L[-x]*R[x];
    }
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef vector<pii> vpii;
typedef vector<pil> vpil;
typedef vector<pli> vpli;
typedef set<int> si;
typedef set<ll> sll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

const double pi = acos(-1.0);
const long long INF = 2e18;

#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define sz size()
#define in insert
#define endl "\n"

#define sqr(a) ((a) * (a))
#define jor(a) !(a&1)// jor means EVEN number
#define bjor(a) (a&1)// bjor means ODD number

#define all(a)  a.begin(), a.end()
#define mem(arr, b) memset(arr, b, sizeof(arr)) //memset only for -1 and 0
//fill(a, a+n, 5) //fill for any value

#define for0(i,b) for(int i=0;i<(b);i++)
#define for1(i,b) for(int i=1;i<=(b);i++)
#define forab(i,a,b) for(int i=(a);i<=(b);i++)
#define forba(i,b,a) for(int i=(b);i>=(a);i--)
#define rep(i,a,b,c) for(int i=(a);i!=(b);i+=(c))

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define fileRead freopen("input.txt", "r", stdin);
#define fileWrite freopen("output.txt", "w", stdout);

void print(int a[], int n){ // for testing or debugging
    for(int i=0;i<n;i++)cout<<a[i]<<" "; cout<<endl;
}

//--------------------------------------------------------------------------

ll f(ll n){
    if(n==1) return 1;
    else {
        return n*(n+1) - n;
    }
}

int main()
{
    ll n; cin>>n;
    map<ll, ll> L,R;
    set<ll> sett;
    for0(i,n) {
        string s; cin>>s;
        bool minusLR=0, minusRL=0;
        ll c=0;
        for(int j=s.sz-1;j>-1;j--){
            if(s[j]=='(') c--;
            else{
                c++;
            }
            if(c==-1) minusRL=1;
        }
        c=0;
        for(auto t:s){
            if(t=='(') c++;
            else{
                c--;
            }
            if(c==-1) minusLR=1;
        }
        if(minusLR and minusRL) {cout<<s<<endl;continue;}
        else {
            if(c>=0) R[c]++;
            else L[c]++;
            sett.in(abs(c));
        }
    }

    ll ans=0;
    for(auto t:sett){
        ll x = abs(t);
        if(x==0){
            ll y = R[t];
            ans+=f(y);
        }
        else ans+=1LL*L[-x]*R[x];
    }
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef vector<pii> vpii;
typedef vector<pil> vpil;
typedef vector<pli> vpli;
typedef set<int> si;
typedef set<ll> sll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

const double pi = acos(-1.0);
const long long INF = 2e18;

#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define sz size()
#define in insert
#define endl "\n"

#define sqr(a) ((a) * (a))
#define jor(a) !(a&1)// jor means EVEN number
#define bjor(a) (a&1)// bjor means ODD number

#define all(a)  a.begin(), a.end()
#define mem(arr, b) memset(arr, b, sizeof(arr)) //memset only for -1 and 0
//fill(a, a+n, 5) //fill for any value

#define for0(i,b) for(int i=0;i<(b);i++)
#define for1(i,b) for(int i=1;i<=(b);i++)
#define forab(i,a,b) for(int i=(a);i<=(b);i++)
#define forba(i,b,a) for(int i=(b);i>=(a);i--)
#define rep(i,a,b,c) for(int i=(a);i!=(b);i+=(c))

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define fileRead freopen("input.txt", "r", stdin);
#define fileWrite freopen("output.txt", "w", stdout);

void print(int a[], int n){ // for testing or debugging
    for(int i=0;i<n;i++)cout<<a[i]<<" "; cout<<endl;
}

//--------------------------------------------------------------------------

ll f(ll n){
    if(n==1) return 1;
    else {
        return n*(n+1) - n;
    }
}

int main()
{
    ll n; cin>>n;
    map<ll, ll> L,R;
    set<ll> sett;
    for0(i,n) {
        string s; cin>>s;
        bool minusLR=0, minusRL=0;
        ll c=0;
        for(int j=s.sz-1;j>-1;j--){
            if(s[j]=='(') c--;
            else{
                c++;
            }
            if(c==-1) minusRL=1;
        }
        c=0;
        for(auto t:s){
            if(t=='(') c++;
            else{
                c--;
            }
            if(c==-1) minusLR=1;
        }
        if(minusLR and minusRL) {continue;}
        else {
            if(c>=0) R[c]++;
            else L[c]++;
            sett.in(abs(c));
        }
    }

    ll ans=0;
    for(auto t:sett){
        ll x = abs(t);
        if(x==0){
            ll y = R[t];
            ans+=f(y);
        }
        else ans+=1LL*L[-x]*R[x];
    }
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef vector<pii> vpii;
typedef vector<pil> vpil;
typedef vector<pli> vpli;
typedef set<int> si;
typedef set<ll> sll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

const double pi = acos(-1.0);
const long long INF = 2e18;

#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define sz size()
#define in insert
#define endl "\n"

#define sqr(a) ((a) * (a))
#define jor(a) !(a&1)// jor means EVEN number
#define bjor(a) (a&1)// bjor means ODD number

#define all(a)  a.begin(), a.end()
#define mem(arr, b) memset(arr, b, sizeof(arr)) //memset only for -1 and 0
//fill(a, a+n, 5) //fill for any value

#define for0(i,b) for(int i=0;i<(b);i++)
#define for1(i,b) for(int i=1;i<=(b);i++)
#define forab(i,a,b) for(int i=(a);i<=(b);i++)
#define forba(i,b,a) for(int i=(b);i>=(a);i--)
#define rep(i,a,b,c) for(int i=(a);i!=(b);i+=(c))

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define fileRead freopen("input.txt", "r", stdin);
#define fileWrite freopen("output.txt", "w", stdout);

void print(int a[], int n){ // for testing or debugging
    for(int i=0;i<n;i++)cout<<a[i]<<" "; cout<<endl;
}

//--------------------------------------------------------------------------

int main()
{
    int n; cin>>n;
    int k; cin>>k;
    int a[n]; for0(i,n) cin>>a[i];
    sort(a,a+n);
    int c=1, mi=0;
    for0(i,n-1){
        if(a[i]==a[i+1]) {c++; continue;}
        else if(a[i]+k>=a[i+1]){
            mi+=c;
            c=1;
        }
    }
    cout<<n-mi;
}


#include<bits/stdc++.h>
using namespace std;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef vector<pii> vpii;
typedef vector<pil> vpil;
typedef vector<pli> vpli;
typedef set<int> si;
typedef set<ll> sll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

const double pi = acos(-1.0);
const long long INF = 2e18;

#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define sz size()
#define in insert
#define endl "\n"

#define sqr(a) ((a) * (a))
#define jor(a) !(a&1)// jor means EVEN number
#define bjor(a) (a&1)// bjor means ODD number

#define all(a)  a.begin(), a.end()
#define mem(arr, b) memset(arr, b, sizeof(arr)) //memset only for -1 and 0
//fill(a, a+n, 5) //fill for any value

#define for0(i,b) for(int i=0;i<(b);i++)
#define for1(i,b) for(int i=1;i<=(b);i++)
#define forab(i,a,b) for(int i=(a);i<=(b);i++)
#define forba(i,b,a) for(int i=(b);i>=(a);i--)
#define rep(i,a,b,c) for(int i=(a);i!=(b);i+=(c))

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define fileRead freopen("input.txt", "r", stdin);
#define fileWrite freopen("output.txt", "w", stdout);

void print(int a[], int n){ // for testing or debugging
    for(int i=0;i<n;i++)cout<<a[i]<<" "; cout<<endl;
}

//--------------------------------------------------------------------------

ll f(ll n){
    if(n==1) return 1;
    else {
        return n*(n+1) - n;
    }
}

int main()
{
    ll n; cin>>n;
    map<ll, ll> L,R;
    si sett;
    for0(i,n) {
        string s; cin>>s;
        bool minus=0;
        ll c=0;
        for(auto t:s){
            if(t=='(') c++;
            else{
                c--;
            }
            if(c==-1) minus=1;
        }
        if((minus and c==0) or (c>0 and minus)) continue;
        else {
            if(c>=0) R[c]++;
            else L[c]++;
            sett.in(abs(c));
        }
    }
    ll ans=0;
    for(auto t:sett){
        ll x = abs(t);
        if(x==0){
            ll y = R[t];
            ans+=f(y);
        }
        else ans+=1LL*L[-x]*R[x];
    }
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef vector<pii> vpii;
typedef vector<pil> vpil;
typedef vector<pli> vpli;
typedef set<int> si;
typedef set<ll> sll;
typedef map<int, int> mii;
typedef map<ll, ll> mll;

const double pi = acos(-1.0);
const long long INF = 2e18;

#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define sz size()
#define in insert
#define endl "\n"

#define sqr(a) ((a) * (a))
#define jor(a) !(a&1)// jor means EVEN number
#define bjor(a) (a&1)// bjor means ODD number

#define all(a)  a.begin(), a.end()
#define mem(arr, b) memset(arr, b, sizeof(arr)) //memset only for -1 and 0
//fill(a, a+n, 5) //fill for any value

#define for0(i,b) for(int i=0;i<(b);i++)
#define for1(i,b) for(int i=1;i<=(b);i++)
#define forab(i,a,b) for(int i=(a);i<=(b);i++)
#define forba(i,b,a) for(int i=(b);i>=(a);i--)
#define rep(i,a,b,c) for(int i=(a);i!=(b);i+=(c))

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define fileRead freopen("input.txt", "r", stdin);
#define fileWrite freopen("output.txt", "w", stdout);

void print(int a[], int n){ // for testing or debugging
    for(int i=0;i<n;i++)cout<<a[i]<<" "; cout<<endl;
}

//--------------------------------------------------------------------------

ll f(ll n){
    if(n==1) return 1;
    else {
        return n*(n+1) - n;
    }
}

int main()
{
    int n; cin>>n;
    //vector<string>L,R;
    map<int, int> L,R;
    si sett;
    for0(i,n) {
        string s; cin>>s;
        bool minus=0;
        int c=0;
        for(auto t:s){
            if(t=='(') c++;
            else{
                c--;
            }
            if(c==-1) minus=1;
        }
        if(minus and c==0) continue;
        else {
            if(c>=0) R[c]++;
            else L[c]++;
            sett.in(abs(c));
        }
    }
    ll ans=0;
    for(auto t:sett){
        int x = abs(t);
        if(x==0){
            ll y = R[t];
            ans+=f(y);
        }
        else ans+=min(L[-x], R[x]);
    }
    cout<<ans;
}