// Arup Guha
// 3/27/2020
// Solution to 2020 UCF HS Contest Problem: Waterfall Quest

/*** Note: I believe the specification for this problem is extremely
           misleading. When I read it, I felt that you would NOT be 
		   able to move from a platform at y=10 from x=5 to x=9 to
		   another platform at y=5 from x=9 to x=11, without the rope
		   because the platforms do NOT overlap at all. It turns out
		   that the judge solution did NOT use this interpretation.
		   I was able to match its output only by allowing that 
		   specific jump without the rope. The way the spec is written
		   I think a better interpretation is to only allow the jump
		   without the rope if there is a range of at least 1 in x
		   that is common to both intervals.
		   
		   If you want to edit my code to use what I feel would be the
		   correct implementation, you must replace x+width with
		   x+width-1 and start+width with start+width-1, where I add
		   to my TreeSet and also when I create my platform objects.
***/

import java.util.*;

public class waterfall {

	public static int n;
	public static platform[] list;
	public static TreeSet<Integer> xList;
	public static HashMap<Integer,Integer> map;
	
	public static void main(String[] args) {
	
		Scanner stdin = new Scanner(System.in);
		int nC = stdin.nextInt();
		
		// Process each case.
		for (int loop=0; loop<nC; loop++) {
		
			// Read in the platforms, store unique x vals for coordinate compression.
			n = stdin.nextInt();
			//System.out.println("starting case "+loop+" and n is "+n);
			list = new platform[n];
			xList = new TreeSet<Integer>();
			for (int i=0; i<n; i++) {
				int x = stdin.nextInt();
				int height = stdin.nextInt();
				int width = stdin.nextInt();
				//if (loop == 4) System.out.println(x+" "+height+" "+width);
				list[i] = new platform(x, height, width);
				xList.add(x);
				xList.add(x+width); /*** x+width-1 ***/
			}
			
			// Store my coordinate compression.
			map = new HashMap<Integer,Integer>();
			int idx = 0;
			while (xList.size() > 0)
				map.put(xList.pollFirst(), idx++);
				
			// Update all my objects accordingly.
			for (int i=0; i<n; i++) {
				list[i].s = map.get(list[i].s);
				list[i].e = map.get(list[i].e);
			}
			
			// Now, sort these guys!
			Arrays.sort(list);
			
			// Add the indexes (into list) of each platform with unique height.
			ArrayList<Integer> uniqueHeightIdx = new ArrayList<Integer>();
			uniqueHeightIdx = new ArrayList<Integer>();
			uniqueHeightIdx.add(0);
			
			int listIdx = 0, prevIdx = 0;
			while (listIdx < n) {
				while (listIdx<n && list[listIdx].h == list[prevIdx].h)
					listIdx++;
				uniqueHeightIdx.add(listIdx);
				prevIdx = listIdx;
			}
			uniqueHeightIdx.add(n);
			
			// At any given time, noJump[i] will equal most jumps from 
			// any platform containing an x coordinate of i. 
			// This seg tree is for situations where you haven't used
			// the rope yet.
			SegTree noJump = new SegTree(0, idx-1);
			
			// When we use the rope, we'll go into this seg tree.
			SegTree didJump = new SegTree(0, idx-1);
			
			int res = 0;
			
			// Go through each set of platforms at the same height.
			for (int i=0; i<uniqueHeightIdx.size()-1; i++) {
			
				// Get boundaries, start(inc), end(exc).
				int startI = uniqueHeightIdx.get(i);
				int endI = uniqueHeightIdx.get(i+1);
				
				// Best answer for all platforms strictly below this batch.
				int allBest = (int)noJump.max(0, idx-1);
				
				// Process using the rope now. We add 1 to prev answer.
				for (int j=startI; j<endI; j++) {
					
					// This is what we could build off of without using our rope here.
					int jumpBest = (int)didJump.max(list[j].s, list[j].e);
					
					// This is the best of using the rope or not using the rope.
					int myres = Math.max(allBest+1, jumpBest+1);
					
					// Here I set the range according to the better of using the rope or not.
					didJump.setRange(list[j].s, list[j].e, myres);
					res = Math.max(res, myres);
				}
				
				// Now, don't use the rope. We add 1 to prev answer in range.
				for (int j=startI; j<endI; j++) {
					int thisBest = (int)noJump.max(list[j].s, list[j].e);
					noJump.setRange(list[j].s, list[j].e, thisBest+1);
					res = Math.max(res, thisBest+1);
				}
			}
			
			// Ta da!
			System.out.println(res);
		}
	}
}

class platform implements Comparable<platform> {

	public int s;
	public int e;
	public int h;
	
	public platform(int start, int height, int width) {
		s = start;
		e = start + width;
		h = height;
	}
	
	// Sorts by height shortest to tallest and then breaks ties by left x.
	public int compareTo(platform other) {
		if (h != other.h) return h-other.h;
		return s - other.s;
	}
}

/*** Josh Fair wrote this for me. Thanks Josh!!! ***/
class SegTree {
	
	// Null value to represent no delta on this node
	static long NULL_DELTA = Long.MIN_VALUE;
	int low, high;
	long max, delta;
	SegTree left, right;
		
	// Constructor for node in range [ll, rr]
	public SegTree(int ll, int rr) {
		low = ll;
		high = rr;
		max = 0;
		delta = NULL_DELTA;
		if(low == high) return;
		int mid = (low+high)/2;
		left = new SegTree(ll, mid);
		right = new SegTree(mid+1, rr);
	}
		
	// Propogate the delta value for this node down
	public void prop() {
		if(left != null && delta != NULL_DELTA) {
			left.set(delta);
			right.set(delta);
			delta = NULL_DELTA;
		}
	}
		
	// Update the sum of the current node
	public void update() {
		if(left != null) {
			max = Math.max(left.max, right.max);
		}
	}
		
	// Set all the values in this node's range to val
	public void set(long val) {
		max = val;
		delta = val;
	}
		
	// Changes range [start, end] to be equal to val
	public void setRange(int start, int end, long val) {
		if(start <= low && high <= end) {
			set(val);
			return;
		}
		if(high < start || end < low) return;
		prop();
		left.setRange(start, end, val);
		right.setRange(start, end, val);
		update();
	}
		
	// Queries the sum of [start, end]
	public long max(int start, int end) {
		if(start <= low && high <= end) return max;
		if(high < start || end < low) return 0;
		prop();
		update();
		return Math.max(left.max(start, end), right.max(start, end));
	}		
}
