description: You are given n segments on a number line, numbered from 1 to n. The i-th segments covers all integer points from l_i to r_i and has a value w_i.
  
  You are asked to select a subset of these segments (possibly, all of them). Once the subset is selected, it's possible to travel between two integer points if there exists a selected segment that covers both of them. A subset is good if it's possible to reach point m starting from point 1 in arbitrary number of moves.
  
  The cost of the subset is the difference between the maximum and the minimum values of segments in it. Find the minimum cost of a good subset.
  
  In every test there exists at least one good subset.
  
  Input
  
  The first line contains two integers n and m (1 ≤ n ≤ 3 ⋅ 10^5; 2 ≤ m ≤ 10^6) — the number of segments and the number of integer points.
  
  Each of the next n lines contains three integers l_i, r_i and w_i (1 ≤ l_i < r_i ≤ m; 1 ≤ w_i ≤ 10^6) — the description of the i-th segment.
  
  In every test there exists at least one good subset.
  
  Output
  
  Print a single integer — the minimum cost of a good subset.
  
  Examples
  
  Input
  
  
  5 12
  1 5 5
  3 4 10
  4 10 6
  11 12 5
  10 12 3
  
  
  Output
  
  
  3
  
  
  Input
  
  
  1 10
  1 10 23
  
  
  Output
  
  
  0
solution: import java.io.IOException;
  import java.io.InputStream;
  import java.io.PrintWriter;
  import java.math.BigDecimal;
  import java.math.RoundingMode;
  import java.util.*;
  
  public class Main {
  	static final long MOD1=1000000007;
  	static final long MOD=998244353;
  	static int ans=0;
  	public static void main(String[] args){
  		PrintWriter out = new PrintWriter(System.out);
  		InputReader sc=new InputReader(System.in);
  		int n = sc.nextInt();
  		int m = sc.nextInt();
  		ArrayList<Pair> list = new ArrayList<>();
  		int[] l = new int[n];
  		int[] r = new int[n];
  		int[] w = new int[n];
  		for (int i = 0; i < w.length; i++) {
  			l[i] = sc.nextInt();
  			if(l[i]==1)l[i]--;
  			r[i] = sc.nextInt();
  			w[i] = sc.nextInt();
  			list.add(new Pair(w[i], i));
  		}
  		Collections.sort(list);
  		LazysegTreemin seg = new LazysegTreemin(m);
  		int min = Integer.MAX_VALUE;
  		int right = 0;     
  		for (int left = 0; left < n; ++left) {
  		    while (right < n){
  		    	Pair p = list.get(right);
  		        seg.apply(l[p.y], r[p.y], 1);
  		        if (seg.prod(0, m)==0) {
  		        	right++;
  				}else {
  					seg.apply(l[p.y], r[p.y], -1);
  					break;
  				}
  		    }
  		    if (right<n)min = Math.min(min, w[list.get(right).y] - w[list.get(left).y]);
  		    /* left をインクリメントする準備 */
  		    if (right == left) {
  		    	min = 0;
  		    	++right;
  		    }else {
  				seg.apply(l[list.get(left).y], r[list.get(left).y], -1);
  			}
  		    //else leftを進めたときの処理;
  		}
  		System.out.println(min);
     	}
  	static class Pair implements Comparable<Pair>{
      	public int x;
      	public int y;
      	public Pair(int x,int y) {
      		this.x=x;
      		this.y=y;
      	}
      	@Override
      	public boolean equals(Object obj) {
      		if(obj instanceof Pair) {
      			Pair other = (Pair) obj;
      			return other.x==this.x && other.y==this.y;
      		}
      		return false;
      	}//同値の定義
      	@Override
      	public int hashCode() {
      		return Objects.hash(this.x,this.y);
      	}//これ書かないと正しく動作しない（要　勉強）
      	@Override
      	public int compareTo( Pair p){
      		if (this.x>p.x) {
      			return 1;
      		}
      		else if (this.x<p.x) {
      			return -1;
      		}
      		else {
      			return 0;
      		}
      	}
      }
  	static class LazysegTreemin{
  		int size;
  		long[] dat;
  		long[] lazy;
  		long INF=Long.MAX_VALUE/2;
  		public LazysegTreemin(int n) {
  			int n_=1;
  			while (n_<n) {
  				n_*=2;
  			}
  			size=n_;
  			dat=new long[2*n_-1];
  			lazy=new long[2*n_-1];
  		}
  		void propagate(int k,int l,int r) {
  			if (lazy[k]!=0) {
  				dat[k] += lazy[k];
  				if(r - l > 1) {
  		            lazy[2*k+1] += lazy[k];
  		            lazy[2*k+2] += lazy[k];
  		        }
  		        lazy[k] = 0;
  			}
  		}
  		void add(int a,int b,long x,int k,int l,int r) {//a<=x<b加算　add(...,0,0,seg.size)で呼ぶ
  			this.propagate(k,l,r);
  			if (a<=l&&r<=b) {
  				lazy[k]+=x;
  				this.propagate(k,l,r);
  			}
  			else if (l<b&&a<r) {//交わっている場合
  				this.add(a, b, x, k*2+1,l,(l+r)/2);
  				this.add(a, b, x, k*2+2, (l+r)/2, r);
  				dat[k] = Math.min(dat[2*k+1],dat[2*k+2]);
  			}
  		}
  		void apply(int a,int b,long x) {
  			this.add(a, b, x, 0, 0, size);
  		}
  		long getmin(int a,int b,int k,int l,int r) {//kが節点番号,l rがその節点番号の範囲
  			if (r<=a||b<=l) {
  				return INF;
  			}
  			this.propagate(k, l, r);
  			if (a<=l&&r<=b) {
  				return dat[k];
  			}
  			else {
  				long vl=this.getmin(a, b, k*2+1,l,(l+r)/2);
  				long vr=this.getmin(a, b, k*2+2, (l+r)/2, r);
  				return (Math.min(vl, vr));
  			}
  		}
  		long prod(int a,int b) {
  			return getmin(a, b, 0, 0, size);
  		}
  	}
  	static class InputReader { 
  		private InputStream in;
  		private byte[] buffer = new byte[1024];
  		private int curbuf;
  		private int lenbuf;
  		public InputReader(InputStream in) {
  			this.in = in;
  			this.curbuf = this.lenbuf = 0;
  		}
  		public boolean hasNextByte() {
  			if (curbuf >= lenbuf) {
  				curbuf = 0;
  				try {
  					lenbuf = in.read(buffer);
  				} catch (IOException e) {
  					throw new InputMismatchException();
  				}
  				if (lenbuf <= 0)
  					return false;
  			}
  			return true;
  		}
   
  		private int readByte() {
  			if (hasNextByte())
  				return buffer[curbuf++];
  			else
  				return -1;
  		}
   
  		private boolean isSpaceChar(int c) {
  			return !(c >= 33 && c <= 126);
  		}
   
  		private void skip() {
  			while (hasNextByte() && isSpaceChar(buffer[curbuf]))
  				curbuf++;
  		}
   
  		public boolean hasNext() {
  			skip();
  			return hasNextByte();
  		}
   
  		public String next() {
  			if (!hasNext())
  				throw new NoSuchElementException();
  			StringBuilder sb = new StringBuilder();
  			int b = readByte();
  			while (!isSpaceChar(b)) {
  				sb.appendCodePoint(b);
  				b = readByte();
  			}
  			return sb.toString();
  		}
   
  		public int nextInt() {
  			if (!hasNext())
  				throw new NoSuchElementException();
  			int c = readByte();
  			while (isSpaceChar(c))
  				c = readByte();
  			boolean minus = false;
  			if (c == '-') {
  				minus = true;
  				c = readByte();
  			}
  			int res = 0;
  			do {
  				if (c < '0' || c > '9')
  					throw new InputMismatchException();
  				res = res * 10 + c - '0';
  				c = readByte();
  			} while (!isSpaceChar(c));
  			return (minus) ? -res : res;
  		}
   
  		public long nextLong() {
  			if (!hasNext())
  				throw new NoSuchElementException();
  			int c = readByte();
  			while (isSpaceChar(c))
  				c = readByte();
  			boolean minus = false;
  			if (c == '-') {
  				minus = true;
  				c = readByte();
  			}
  			long res = 0;
  			do {
  				if (c < '0' || c > '9')
  					throw new InputMismatchException();
  				res = res * 10 + c - '0';
  				c = readByte();
  			} while (!isSpaceChar(c));
  			return (minus) ? -res : res;
  		}
   
  		public double nextDouble() {
  			return Double.parseDouble(next());
  		}
   
  		public int[] nextIntArray(int n) {
  			int[] a = new int[n];
  			for (int i = 0; i < n; i++)
  				a[i] = nextInt();
  			return a;
  		}
  		public double[] nextDoubleArray(int n) {
  			double[] a = new double[n];
  			for (int i = 0; i < n; i++)
  				a[i] = nextDouble();
  			return a;
  		}
  		public long[] nextLongArray(int n) {
  			long[] a = new long[n];
  			for (int i = 0; i < n; i++)
  				a[i] = nextLong();
  			return a;
  		}
   
  		public char[][] nextCharMap(int n, int m) {
  			char[][] map = new char[n][m];
  			for (int i = 0; i < n; i++)
  				map[i] = next().toCharArray();
  			return map;
  		}
  	}
  }
  