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: /*
  stream Butter!
  eggyHide eggyVengeance
  I need U
  xiao rerun when
   */
  import static java.lang.Math.*;
  import java.util.*;
  import java.io.*;
  import java.math.*;
  
  public class x1555E
  {
      static final int MAX = 1000000;
      public static void main(String hi[]) throws Exception
      {
          FastScanner infile = new FastScanner();
          int N = infile.nextInt();
          int M = infile.nextInt();
          ArrayDeque<Range>[] buckets = new ArrayDeque[MAX+1];
          for(int i=1; i <= MAX; i++)
              buckets[i] = new ArrayDeque<Range>();
          for(int i=0; i < N; i++)
          {
              int a = infile.nextInt();
              int b = infile.nextInt();
              int w = infile.nextInt();
              buckets[w].add(new Range(a, b));
          }
          LazySegTree active = new LazySegTree(2*M+3);
          //active.update(2, 2, 1);
          //System.out.println("! "+active.query(2, 2));
          int res = Integer.MAX_VALUE/2;
          int pointer = 1;
          for(int i=1; i <= MAX; i++)
          {
              while(pointer <= MAX && active.query(2, 2*M) == 0)
              {
                  for(Range r: buckets[pointer])
                      active.update(r.left<<1, r.right<<1, 1);
                  pointer++;
              }
              if(pointer > MAX && active.query(2, 2*M) == 0)
                  break;
              res = min(res, pointer-i-1);
              for(Range r: buckets[i])
                  active.update(r.left<<1, r.right<<1, -1);
          }
          System.out.println(res);
      }
  }
  class LazySegTree
  {
      //definitions
      private int NULL = Integer.MAX_VALUE/2;
      private int[] tree;
      private int[] lazy;
      private int length;
  
      public LazySegTree(int N)
      {
          length = N;   int b;
          for(b=0; (1<<b) < length; b++);
          tree = new int[1<<(b+1)];
          lazy = new int[1<<(b+1)];
      }
      public int query(int left, int right)
      {
          //left and right are 0-indexed
          return get(1, 0, length-1, left, right);
      }
      private int get(int v, int currL, int currR, int L, int R)
      {
          if(L > R)
              return NULL;
          if(L <= currL && currR <= R)
              return tree[v];
          propagate(v);
          int mid = (currL+currR)/2;
          return comb(get(v*2, currL, mid, L, Math.min(R, mid)),
                  get(v*2+1, mid+1, currR, Math.max(L, mid+1), R));
      }
      public void update(int left, int right, int delta)
      {
          add(1, 0, length-1, left, right, delta);
      }
      private void add(int v, int currL, int currR, int L, int R, int delta)
      {
          if(L > R)
              return;
          if(currL == L && currR == R)
          {
              //exact covering
              tree[v] += delta;
              lazy[v] += delta;
              return;
          }
          propagate(v);
          int mid = (currL+currR)/2;
          add(v*2, currL, mid, L, Math.min(R, mid), delta);
          add(v*2+1, mid+1, currR, Math.max(L, mid+1), R, delta);
          tree[v] = comb(tree[v*2], tree[v*2+1]);
      }
      private void propagate(int v)
      {
          //tree[v] already has lazy[v]
          if(lazy[v] == 0)
              return;
          tree[v*2] += lazy[v];
          lazy[v*2] += lazy[v];
          tree[v*2+1] += lazy[v];
          lazy[v*2+1] += lazy[v];
          lazy[v] = 0;
      }
      private int comb(int a, int b)
      {
          return min(a,b);
      }
  }
  class Range
  {
      public int left;
      public int right;
  
      public Range(int a, int b)
      {
          left = a;
          right = b;
      }
  }
  class FastScanner
  {
      //I don't understand how this works lmao
      private int BS = 1 << 16;
      private char NC = (char) 0;
      private byte[] buf = new byte[BS];
      private int bId = 0, size = 0;
      private char c = NC;
      private double cnt = 1;
      private BufferedInputStream in;
  
      public FastScanner() {
          in = new BufferedInputStream(System.in, BS);
      }
  
      public FastScanner(String s) {
          try {
              in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
          } catch (Exception e) {
              in = new BufferedInputStream(System.in, BS);
          }
      }
  
      private char getChar() {
          while (bId == size) {
              try {
                  size = in.read(buf);
              } catch (Exception e) {
                  return NC;
              }
              if (size == -1) return NC;
              bId = 0;
          }
          return (char) buf[bId++];
      }
  
      public int nextInt() {
          return (int) nextLong();
      }
  
      public int[] nextInts(int N) {
          int[] res = new int[N];
          for (int i = 0; i < N; i++) {
              res[i] = (int) nextLong();
          }
          return res;
      }
  
      public long[] nextLongs(int N) {
          long[] res = new long[N];
          for (int i = 0; i < N; i++) {
              res[i] = nextLong();
          }
          return res;
      }
  
      public long nextLong() {
          cnt = 1;
          boolean neg = false;
          if (c == NC) c = getChar();
          for (; (c < '0' || c > '9'); c = getChar()) {
              if (c == '-') neg = true;
          }
          long res = 0;
          for (; c >= '0' && c <= '9'; c = getChar()) {
              res = (res << 3) + (res << 1) + c - '0';
              cnt *= 10;
          }
          return neg ? -res : res;
      }
  
      public double nextDouble() {
          double cur = nextLong();
          return c != '.' ? cur : cur + nextLong() / cnt;
      }
  
      public double[] nextDoubles(int N) {
          double[] res = new double[N];
          for (int i = 0; i < N; i++) {
              res[i] = nextDouble();
          }
          return res;
      }
  
      public String next() {
          StringBuilder res = new StringBuilder();
          while (c <= 32) c = getChar();
          while (c > 32) {
              res.append(c);
              c = getChar();
          }
          return res.toString();
      }
  
      public String nextLine() {
          StringBuilder res = new StringBuilder();
          while (c <= 32) c = getChar();
          while (c != '\n') {
              res.append(c);
              c = getChar();
          }
          return res.toString();
      }
  
      public boolean hasNext() {
          if (c > 32) return true;
          while (true) {
              c = getChar();
              if (c == NC) return false;
              else if (c > 32) return true;
          }
      }
  }