Maksim walks on a Cartesian plane. Initially, he stands at the point $$$(0, 0)$$$ and in one move he can go to any of four adjacent points (left, right, up, down). For example, if Maksim is currently at the point $$$(0, 0)$$$, he can go to any of the following points in one move:   $$$(1, 0)$$$;  $$$(0, 1)$$$;  $$$(-1, 0)$$$;  $$$(0, -1)$$$. There are also $$$n$$$ distinct key points at this plane. The $$$i$$$-th point is $$$p_i = (x_i, y_i)$$$. It is guaranteed that $$$0 \le x_i$$$ and $$$0 \le y_i$$$ and there is no key point $$$(0, 0)$$$.Let the first level points be such points that $$$max(x_i, y_i) = 1$$$, the second level points be such points that $$$max(x_i, y_i) = 2$$$ and so on. Maksim wants to visit all the key points. But he shouldn't visit points of level $$$i + 1$$$ if he does not visit all the points of level $$$i$$$. He starts visiting the points from the minimum level of point from the given set.The distance between two points $$$(x_1, y_1)$$$ and $$$(x_2, y_2)$$$ is $$$|x_1 - x_2| + |y_1 - y_2|$$$ where $$$|v|$$$ is the absolute value of $$$v$$$.Maksim wants to visit all the key points in such a way that the total distance he walks will be minimum possible. Your task is to find this distance.If you are Python programmer, consider using PyPy instead of Python when you submit your code.

The first line of the input contains one integer $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$) — the number of key points. Each of the next $$$n$$$ lines contains two integers $$$x_i$$$, $$$y_i$$$ ($$$0 \le x_i, y_i \le 10^9$$$) — $$$x$$$-coordinate of the key point $$$p_i$$$ and $$$y$$$-coordinate of the key point $$$p_i$$$. It is guaranteed that all the points are distinct and the point $$$(0, 0)$$$ is not in this set.

Print one integer — the minimum possible total distance Maksim has to travel if he needs to visit all key points in a way described above.

NoteThe picture corresponding to the first example: There is one of the possible answers of length $$$15$$$.The picture corresponding to the second example: There is one of the possible answers of length $$$9$$$.

import java.util.*;

public class ContestE {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Map<Integer, Integer[][]> map = new HashMap<>();
    	map.put(0, new Integer[][] {
    		{0,0},// top left
    		{0,0}// bottom right
    	});
        for(int i=0;i<n;i++){
        	int x = in.nextInt();
        	int y = in.nextInt();
        	int l = Math.max(x, y);
        	if(map.containsKey(l)) {
        		Integer arr[][] = map.get(l);
        		if(y-x>arr[0][1]-arr[0][0]) {
        			arr[0][0] = x;
        			arr[0][1] = y;
        		}
        		if(y-x<arr[1][1]-arr[1][0]) {
        			arr[1][0] = x;
        			arr[1][1] = y;
        		}
        	}else {
            	map.put(l, new Integer[][] {
            		{x,y},// top left
            		{x,y}// bottom right
            	});
        	}
        }
        int prevLevel = -1;
        long distancetop = 0;
        long distancebottom = 0;
        SortedSet<Integer> keys = new TreeSet<>(map.keySet());
        for(Integer key: keys) {
        	Integer arr[][] = map.get(key);
        	if(prevLevel>=0) {
	        	Integer arrPrev[][] = map.get(prevLevel);
	        	long tmpdistancetop =
	        			Math.min(distancebottom + distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1]),
	        					distancetop + distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]));
	        	long tmpdistancebottom =
	        			Math.min(distancebottom + distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1]),
	        					distancetop + distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]));
	        	distancetop = tmpdistancebottom + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
	        	distancebottom = tmpdistancetop + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
        	}
        	prevLevel = key;
        }
        System.out.println(Math.min(distancebottom, distancetop));
        in.close();
	}

	public static long distance(long x1, long y1, long x2, long y2) {
		return Math.abs(x1-x2)+Math.abs(y1-y2);
	}
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.SplittableRandom;
import java.util.Comparator;
import java.util.Collections;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastReader in = new FastReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskF solver = new TaskF();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskF {
        int n;
        TaskF.Point[] arr;
        List<List<TaskF.Point>> layers = new ArrayList<>();

        public void solve(int testNumber, FastReader in, PrintWriter out) {
            n = in.nextInt();
            arr = new TaskF.Point[n];
            for (int i = 0; i < n; i++) {
                long x = in.nextLong();
                long y = in.nextLong();
                arr[i] = new TaskF.Point(x, y);
            }

            ArrayUtils.sort(arr);
            List<TaskF.Point> first = new ArrayList<>();
            first.add(new TaskF.Point(0, 0));
            layers.add(first);
            int start = 0;
            while (start < n) {
                int end = start;
                List<TaskF.Point> ls = new ArrayList<>();
                while (end < n && arr[end].max == arr[start].max) {
                    ls.add(arr[end]);
                    end++;
                }

                layers.add(ls);
                start = end;
            }

            for (List<TaskF.Point> layer : layers) {
                Collections.sort(layer, new Comparator<TaskF.Point>() {

                    public int compare(TaskF.Point o1, TaskF.Point o2) {
                        if (o1.x != o2.x) {
                            return Long.compare(o1.x, o2.x);
                        }

                        return Long.compare(o2.y, o1.y);
                    }
                });
            }

            int sz = layers.size();
            long[][] dp = new long[sz][2];
            dp[0][0] = 0;
            dp[0][1] = 0;
            for (int i = 1; i < sz; i++) {
                Arrays.fill(dp[i], Long.MAX_VALUE);
            }

            for (int i = 0; i < sz - 1; i++) {
                //start from dp[i][0]
                TaskF.Point c0 = layers.get(i).get(0);
                int m = layers.get(i).size();
                TaskF.Point c1 = layers.get(i).get(m - 1);

                TaskF.Point n0 = layers.get(i + 1).get(0);
                m = layers.get(i + 1).size();
                TaskF.Point n1 = layers.get(i + 1).get(m - 1);

                dp[i + 1][1] = Math.min(dp[i + 1][1], dp[i][0] + dist(c0, n0) + dist(n0, n1));
                dp[i + 1][0] = Math.min(dp[i + 1][0], dp[i][0] + dist(c0, n1) + dist(n1, n0));

                dp[i + 1][1] = Math.min(dp[i + 1][1], dp[i][1] + dist(c1, n0) + dist(n0, n1));
                dp[i + 1][0] = Math.min(dp[i + 1][0], dp[i][1] + dist(c1, n1) + dist(n1, n0));
            }

            out.println(Math.min(dp[sz - 1][0], dp[sz - 1][1]));
        }

        long dist(TaskF.Point p1, TaskF.Point p2) {
            return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
        }

        static class Point implements Comparable<TaskF.Point> {
            long x;
            long y;
            long max;

            public Point(long x, long y) {
                this.x = x;
                this.y = y;
                max = Math.max(x, y);
            }

            public int compareTo(TaskF.Point o) {
                return Long.compare(max, o.max);
            }

            public String toString() {
                return x + " " + y;
            }

        }

    }

    static class FastReader {
        private InputStream stream;
        private byte[] buf = new byte[8192];
        private int curChar;
        private int pnumChars;

        public FastReader(InputStream stream) {
            this.stream = stream;
        }

        private int pread() {
            if (pnumChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= pnumChars) {
                curChar = 0;
                try {
                    pnumChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (pnumChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = pread();
            while (isSpaceChar(c))
                c = pread();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = pread();
            }
            int res = 0;
            do {
                if (c == ',') {
                    c = pread();
                }
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = pread();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = pread();
            while (isSpaceChar(c))
                c = pread();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = pread();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = pread();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        private boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

    }

    static class ArrayUtils {
        public static Object[] sort(Object[] a) {
            a = shuffle(a, new SplittableRandom());
            Arrays.sort(a);
            return a;
        }

        public static Object[] shuffle(Object[] a, SplittableRandom gen) {
            for (int i = 0, n = a.length; i < n; i++) {
                int ind = gen.nextInt(n - i) + i;
                Object d = a[i];
                a[i] = a[ind];
                a[ind] = d;
            }
            return a;
        }

    }
}

import java.util.*;
import java.io.*;

// Solution

public class Main
{
  public static void main (String[] argv)
  {
	  new Main();
  }

  boolean test = false;

  final int MOD = 998244353;

  class Point {
      int x, y;
      public Point(int xx, int yy) {
          x = xx;
          y = yy;
      }
  }

  class Line implements Comparable<Line> {
      Point left, right;
      int level;
      public Line(int level) {
          left = null;
          right = null;
          this.level = level;
      }

      @Override
      public int compareTo(Line o) {
          return level - o.level;
      }
  }
  public Main()   {
	 FastReader in = new FastReader(new BufferedReader(new InputStreamReader(System.in)));
	// FastReader in = new FastReader(new BufferedReader(new FileReader("Main.in")));
     int n = in.nextInt();
     List<Line> list = new ArrayList<>();
     Map<Integer, Line> map = new HashMap<>();
     for (int i = 0; i < n; i++) {
         int x = in.nextInt();
         int y = in.nextInt();
         int level = max(x, y);
         if (map.containsKey(level)) {
             add(map.get(level), x, y);
         }else {
             Line line = new Line(level);
             line.left = new Point(x, y);
             map.put(level, line);
         }
     }

     for (Line line : map.values())
         list.add(line);

     Collections.sort(list);

     long dp_L = 0;
     long dp2_L = 0;
     long dp_R = 0;
     long dp2_R = 0;
     Point pL = new Point(0, 0);
     Point pR = null;
     for (Line line : list) {
         long line_dist = dist(line.left, line.right);
         if (line.right == null) line.right = line.left;

         dp2_L = dp_L + dist(pL, line.right) + line_dist;
         if (pR != null)
             dp2_L = min(dp2_L, dp_R + dist(pR, line.right) + line_dist);

         dp2_R = dp_L + dist(pL, line.left) + line_dist;
         if (pR != null)
             dp2_R = min(dp2_R, dp_R + dist(pR, line.left) + line_dist);

         //System.out.print("current line dist = " + line_dist + ", points: " + line.left.x + " " + line.left.y);
         //if (line.right != null) System.out.println(" " + line.right.x + " " + line.right.y);
         //else System.out.println();

         //System.out.println("min dist to level " + line.level + " = " + dp2_L + ", " + dp2_R);
         // update pL and pR
         pL = line.left;
         pR = line.right;

         dp_L = dp2_L;
         dp_R = dp2_R;
     }
     System.out.println(Math.min(dp_L, dp_R));
  }

  private long dist(Point p1, Point p2) {
      if (p2 == null) return 0;

      return abs(p1.x - p2.x) + abs(p1.y - p2.y);
  }

  private void add(Line line, int x, int y) {
      if (line.right != null) {
          if (less(x, y, line.left.x, line.left.y)) {
              line.left.x = x;
              line.left.y = y;
          }else if (less(line.right.x, line.right.y, x, y)){
              line.right.x = x;
              line.right.y = y;
          }
      }else {
          if (less(x, y, line.left.x, line.left.y)) {
              line.right = new Point(line.left.x, line.left.y);
              line.left.x = x;
              line.left.y = y;
          }else {
              line.right = new Point(x, y);
          }
      }
  }

  private boolean less(int x, int y, int xx, int yy) {
      return x < xx || y > yy;
  }

  private int mul(int x, int y) {
      return (int)(1L * x * y % MOD);
  }

  private int add(int x, int y) {
      return (x + y) % MOD;
  }

  private int nBit1(int v) {
      int v0 = v;
      int c = 0;
      while (v != 0) {
          ++c;
          v = v & (v - 1);
      }
      return c;
  }

  private long abs(long v) {
      return v > 0 ? v : -v;
  }

  private int abs(int v) {
      return v > 0 ? v : -v;
  }

  private int common(int v) {
      int c = 0;
      while (v != 1) {
          v = (v >>> 1);
          ++c;
      }

      return c;
  }

  private void reverse(char[] a, int i, int j) {
      while (i < j) {
          swap(a, i++, j--);
      }
  }

  private void swap(char[] a, int i, int j) {
      char t = a[i];
      a[i] = a[j];
      a[j] = t;
  }

  private int gcd(int x, int y) {
      if (y == 0) return x;
      return gcd(y, x % y);
  }
  private long gcd(long x, long y) {
      if (y == 0) return x;
      return gcd(y, x % y);
  }
  private int max(int a, int b) {
      return a >  b ? a : b;
  }

  private long max(long a, long b) {
      return a >  b ? a : b;
  }

  private int min(int a, int b) {
      return a >  b ? b : a;
  }

  private long min(long a, long b) {
      return a >  b ? b : a;
  }

  static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader(BufferedReader in)
        {
            br = in;
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    String line = br.readLine();
                    if (line == null || line.length() == 0) return "";
                    st = new StringTokenizer(line);
                }
                catch (IOException  e)
                {
                    return "";
                    //e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                return "";
                //e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.*;
public class YA2DWalking {
    public static void main(String[] args) {
        FastScanner scanner = new FastScanner();
        int N = scanner.nextInt();
        PriorityQueue<Point> queue = new PriorityQueue<>();
        for(int i = 0; i < N; i++) {
            queue.add(new Point(scanner.nextInt(), scanner.nextInt()));
        }
        int curLevel = 0;
        long[][] dp = new long[N+1][2];
        for(int i = 0; i <= N; i++) {
            Arrays.fill(dp[i], Long.MAX_VALUE);
        }
        dp[0][0] = dp[0][1] = 0L;
        Point[][] poi = new Point[N+1][2];
        poi[0][0] = new Point(0,0);
        poi[0][1] = new Point(0, 0);
        while(!queue.isEmpty()) {
            curLevel++;
            Point p1 = queue.poll();
            Point p2 = null;
            while(!queue.isEmpty() && queue.peek().level==p1.level) p2 = queue.poll();
            if (p2 == null) p2 = p1;
            poi[curLevel][0] = p1;
            poi[curLevel][1] = p2;
            dp[curLevel][0] = Math.min(dp[curLevel][0], dp[curLevel-1][1] + dist(p2, poi[curLevel-1][1]) + dist(p1, p2));
            dp[curLevel][0] = Math.min(dp[curLevel][0], dp[curLevel-1][0] + dist(p2, poi[curLevel-1][0]) + dist(p1, p2));
            dp[curLevel][1] = Math.min(dp[curLevel][1], dp[curLevel-1][1] + dist(p1, poi[curLevel-1][1]) + dist(p1, p2));
            dp[curLevel][1] = Math.min(dp[curLevel][1], dp[curLevel-1][0] + dist(p1, poi[curLevel-1][0]) + dist(p1, p2));
        }
        System.out.println(Math.min(dp[curLevel][0], dp[curLevel][1]));
    }
    public static long dist(Point a, Point b) {
        return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
    }
    public static class Point implements Comparable<Point>{
        int x, y, level;
        public Point(int xx, int yy) {
            x = xx;
            y = yy;
            level = Math.max(xx, yy);
        }
        public int compareTo(Point o) {
            if (this.level == o.level) {
                if (this.x == o.x) return Integer.compare(o.y, this.y);
                return Integer.compare(this.x, o.x);
            }
            return Integer.compare(this.level, o.level);
        }
    }
    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;
        public FastScanner(Reader in) {
            br = new BufferedReader(in);
        }
        public FastScanner() {
            this(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String readNextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
        int[] readIntArray(int n) {
            int[] a = new int[n];
            for (int idx = 0; idx < n; idx++) {
                a[idx] = nextInt();
            }
            return a;
        }
    }
}

import java.util.*;
import java.io.*;
public final class CF {
    static class Pair implements Comparable<Pair> {
        long x, y, max;
        Pair(long x, long y) {
            this.x = x;
            this.y = y;
            this.max = Math.max(x, y);
        }
        public int compareTo(Pair other) {
            return Long.compare(this.max, other.max);
        }
    }
    static long dist(Pair p1, Pair p2) {
        return Math.abs(p1.x-p2.x)+Math.abs(p1.y-p2.y);
    }
    public static void main (String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Pair[] a = new Pair[n];
        for(int i = 0; i<n; i++)
            a[i] = new Pair(sc.nextLong(), sc.nextLong());
        Arrays.sort(a);
        List<Pair> first = new ArrayList<>();
        first.add(new Pair(0, 0));
        List<List<Pair>> layer = new ArrayList<>();
        layer.add(first);
        int start = 0;
        while(start<n) {
            int end = start;
            List<Pair> li = new ArrayList<>();
            while(end<n && a[end].max==a[start].max) {
                li.add(a[end]);
                end++;
            }
            layer.add(li);
            start = end;
        }
        for(List<Pair> i: layer) {
            Collections.sort(i, new Comparator<Pair>() {
                @Override
                public int compare(Pair p1, Pair p2) {
                    if(p1.x!=p2.x)
                        return Long.compare(p1.x, p2.x);
                    return Long.compare(p2.y, p1.y);
                }
            });
        }
        int size = layer.size();
        long[][] dp = new long[size][2];
        dp[0][0] = 0;
        dp[0][1] = 0;
        for(int i = 1; i<size; i++)
            Arrays.fill(dp[i], Long.MAX_VALUE);
        for(int i = 0; i<size-1; i++) {
            Pair c0 = layer.get(i).get(0);
            int m = layer.get(i).size();
            Pair c1 = layer.get(i).get(m-1);

            Pair n0 = layer.get(i+1).get(0);
            m = layer.get(i+1).size();
            Pair n1 = layer.get(i+1).get(m-1);

            dp[i+1][0] = Math.min(dp[i+1][0], dp[i][0]+dist(c0, n1)+dist(n1, n0));
            dp[i+1][0] = Math.min(dp[i+1][0], dp[i][1]+dist(c1, n1)+dist(n1, n0));
            dp[i+1][1] = Math.min(dp[i+1][1], dp[i][0]+dist(c0, n0)+dist(n0, n1));
            dp[i+1][1] = Math.min(dp[i+1][1], dp[i][1]+dist(c1, n0)+dist(n0, n1));
        }
        System.out.println(Math.min(dp[size-1][0], dp[size-1][1]));
    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.TreeMap;
import java.io.IOException;
import java.io.BufferedReader;
import java.util.Collections;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Vadim
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskF solver = new TaskF();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskF {
        static long getDist(TaskF.Point p1, TaskF.Point p2) {
            return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.ni();
            TaskF.Point[] points = new TaskF.Point[n];
            TreeMap<Integer, Integer> coords = new TreeMap<>();
            for (int i = 0; i < n; i++) {
                int x = in.ni();
                int y = in.ni();
                coords.put(Math.max(x, y), 0);
                points[i] = new TaskF.Point(x, y);
            }
            int max_level = coords.size();
            int[] levels = new int[max_level + 1];
            int level = 1;
            for (Integer coord : coords.keySet()) {
                coords.put(coord, level);
                levels[level++] = coord;
            }
            ArrayList<Integer>[] ypoints = new ArrayList[max_level + 1];
            ArrayList<Integer>[] xpoints = new ArrayList[max_level + 1];
            for (int i = 0; i < max_level + 1; i++) {
                ypoints[i] = new ArrayList<>();
                xpoints[i] = new ArrayList<>();
            }
            for (int i = 0; i < n; i++) {
                TaskF.Point p = points[i];
                if (p.x >= p.y) {
                    xpoints[coords.get(p.x)].add(p.y);
                } else {
                    ypoints[coords.get(p.y)].add(p.x);
                }
            }
            for (int i = 0; i < max_level + 1; i++) {
                if (!xpoints[i].isEmpty())
                    Collections.sort(xpoints[i]);
                if (!ypoints[i].isEmpty())
                    Collections.sort(ypoints[i]);
            }
            long[] levelDist = new long[max_level + 1];
            TaskF.Point[][] levelPoints = new TaskF.Point[max_level + 1][2];
            levelPoints[0][0] = levelPoints[0][1] = new TaskF.Point(0, 0);
            for (int i = 1; i < max_level + 1; i++) {
                long dist = 0;
                if (!xpoints[i].isEmpty()) {
                    int maxy = xpoints[i].get(xpoints[i].size() - 1);
                    dist = maxy - xpoints[i].get(0);
                    levelPoints[i][0] = new TaskF.Point(levels[i], xpoints[i].get(0)); //min point
                    levelPoints[i][1] = new TaskF.Point(levels[i], maxy);
                }
                if (!ypoints[i].isEmpty()) {
                    int maxx = ypoints[i].get(ypoints[i].size() - 1);
                    dist += maxx - ypoints[i].get(0);
                    if (xpoints[i].isEmpty()) {
                        levelPoints[i][0] = new TaskF.Point(maxx, levels[i]);
                        levelPoints[i][1] = new TaskF.Point(ypoints[i].get(0), levels[i]);
                    } else {
                        dist += getDist(levelPoints[i][1], new TaskF.Point(ypoints[i].get(ypoints[i].size() - 1), levels[i]));
                        levelPoints[i][1] = new TaskF.Point(ypoints[i].get(0), levels[i]);
                    }
                }
                levelDist[i] = dist;
            }
            long d[][] = new long[max_level + 1][2];
            int prevLevel = 0;
            for (level = 1; level < max_level + 1; level++) {
                assert levelPoints[level][0] != null;
                assert levelPoints[level][1] != null;
                assert levelPoints[prevLevel][0] != null;
                assert levelPoints[prevLevel][1] != null;
                d[level][0] += Math.min(d[prevLevel][0] + getDist(levelPoints[level][1], levelPoints[prevLevel][0]), d[prevLevel][1] + getDist(levelPoints[level][1], levelPoints[prevLevel][1])) + levelDist[level];
                d[level][1] += Math.min(d[prevLevel][0] + getDist(levelPoints[level][0], levelPoints[prevLevel][0]), d[prevLevel][1] + getDist(levelPoints[level][0], levelPoints[prevLevel][1])) + levelDist[level];
                prevLevel = level;
            }

            out.println(Math.min(d[prevLevel][0], d[prevLevel][1]));
        }

        static class Point {
            int x;
            int y;

            public Point(int x, int y) {
                this.x = x;
                this.y = y;
            }

        }

    }

    static class InputReader extends BufferedReader {
        public InputReader(InputStream st) {
            super(new InputStreamReader(st));
        }

        public String readLine() {
            try {
                return super.readLine();
            } catch (IOException e) {
                return null;
            }
        }

        private int readByte() {
            try {
                return read();
            } catch (IOException e) {
                throw new RuntimeException();
            }
        }

        public int ni() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

    }
}

import java.io.*;
import java.util.*;

public class F {
    public static void main(String[] args) throws Throwable {
        MyScanner sc = new MyScanner();
        PrintWriter pw = new PrintWriter(System.out);

        int n=sc.nextInt();
        int [] x=new int [n];
        int [] y=new int [n];

        TreeSet<Integer> set=new TreeSet<>();
        HashMap<Integer,Integer> map=new HashMap();
        for(int i=0;i<n;i++){
            x[i]=sc.nextInt();
            y[i]=sc.nextInt();
            set.add(Math.max(x[i],y[i]));
        }
        int id=0;
        for(int xx : set)
            map.put(xx,id++);

        pair [] p1=new pair [id];
        pair [] p2=new pair [id];
        ArrayList<pair> [] arr=new ArrayList[id];
        for(int i=0;i<id;i++)
            arr[i]=new ArrayList<>();
        for(int i=0;i<n;i++){
            pair p=new pair(x[i],y[i]);
            int mx=Math.max(x[i],y[i]);
            mx=map.get(mx);
            arr[mx].add(p);
        }
        long [] dis=new long [id];
        for(int i=0;i<id;i++){
            Collections.sort(arr[i]);
            for(int j=0;j<arr[i].size()-1;j++){
                dis[i]+=Math.abs(arr[i].get(j).x-arr[i].get(j+1).x);
                dis[i]+=Math.abs(arr[i].get(j).y-arr[i].get(j+1).y);
            }
            p1[i]=arr[i].get(0);
            p2[i]=arr[i].get(arr[i].size()-1);
        }

        long [][] dp=new long [id+1][2];
        dp[id-1][0]=dp[id-1][1]=dis[id-1];

        for(int i=id-2;i>=0;i--){
            for(int j=0;j<2;j++){
                dp[i][j]=dis[i];
                if(j==0){
                    dp[i][j]+=Math.min(
                            Math.abs(p2[i].x-p1[i+1].x)+Math.abs(p2[i].y-p1[i+1].y)+dp[i+1][0]
                            ,Math.abs(p2[i].x-p2[i+1].x)+Math.abs(p2[i].y-p2[i+1].y)+dp[i+1][1]);
                }else{

                    dp[i][j]+=Math.min(
                            Math.abs(p1[i].x-p1[i+1].x)+Math.abs(p1[i].y-p1[i+1].y)+dp[i+1][0]
                            ,Math.abs(p1[i].x-p2[i+1].x)+Math.abs(p1[i].y-p2[i+1].y)+dp[i+1][1]);
                }
            }
        }

        pw.println(Math.min(p1[0].x+p1[0].y+dp[0][0],p2[0].x+p2[0].y+dp[0][1]));

        pw.flush();
        pw.close();
    }

    static class pair implements Comparable<pair>{
        int x,y;
        pair(int a,int b){
            x=a;
            y=b;
        }
        public int compareTo(pair p){
            if(x!=p.x)
                return x-p.x;
            return p.y-y;
        }
    }

    static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException;

import java.io.*;
import java.util.*;

public class E1066 {

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver1066D solver = new Solver1066D();
        solver.solve(inp, out);
        out.close();
    }

    static class InputReader {
        StringTokenizer tokenizer;
        InputStreamReader sReader;
        BufferedReader reader;

        InputReader(InputStream stream) {
            sReader = new InputStreamReader(stream);
            reader = new BufferedReader(sReader, 32768);
            tokenizer = null;
        }

        String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public List<Integer> intLine(int size) {
            List<Integer> ls = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                ls.add(nextInt());
            }
            return ls;
        }

        int nextC() {
            try {
                return reader.read();
            } catch (IOException e) {
                return -1;
            }
        }

        public int[] intArr(int size) {
            int[] ls = new int[size];
            for (int i = 0; i < size; i++){
                ls[i] = nextInt();
            }
            return ls;
        }
    }

    static class Solver1066D {
        HashMap<Integer, Level> hm = new HashMap<>();
        public void solve(InputReader inp, PrintWriter out) {
            int n = inp.nextInt(), i;
            for (i=0; i < n; i++){
                int x = inp.nextInt(), y = inp.nextInt();
                int lev = Math.max(x, y);
                if (!hm.containsKey(lev)) hm.put(lev, new Level(lev));
                hm.get(lev).addv(x, y);
            }
            List<Integer> existing = new ArrayList<>(hm.keySet());
            Collections.sort(existing);

            Level Null = new Level(0);
            Level curr = Null;

            for (i = 0; i < existing.size(); i++){
                Level ne = hm.get(existing.get(i));
                curr.next = ne;
                curr = ne;
            }
            out.println(Null.traverse(0, 0));
//            for (i = 0; i < existing.size(); i++){
//                Level ne = hm.get(existing.get(i));
//                out.println(existing.get(i)+": "+ ne);
//            }

        }

        class Level{
            int lev, minx, miny, maxx, maxy, d=-1;
            long d1, d2;
            Level next;
            boolean b1 = false, b2 = false;
            Level(int lev){
                this.lev = lev;
                this.minx = lev;
                this.miny = lev;
            }
            void addv(int x, int y){
                if (x > this.maxx) maxx = x;
                if (x < this.minx) minx = x;
                if (y > this.maxy) maxy = y;
                if (y < this.miny) miny = y;
            }
            int d(){
                if (this.d == -1){
                    this.d = dist(this.maxx, this.miny, this.minx, this.maxy);
                }
                return this.d;
            }
            long traverse(int x, int y){
//                System.out.println("traversing "+x+", "+y);
                if (this.next == null) return this.d();
                if (x == this.maxx && y == this.miny){
                    if (this.b1) return this.d1;

                    this.d1 = this.d()+acttraverse(this.minx, this.maxy);
                    this.b1 = true;
                    return this.d1;
                }
                else if (x == this.minx && y == this.maxy){
                    if (this.b2) return this.d2;

                    this.d2 = this.d()+acttraverse(this.maxx, this.miny);
                    this.b2 = true;
                    return this.d2;
                } else {
                    System.out.println("what happened");
                    return -1;
                }
            }

            long acttraverse(int x, int y){
                long d1 = dist(this.next.maxx, this.next.miny, x, y) + this.next.traverse(this.next.maxx, this.next.miny);
                long d2 = dist(this.next.minx, this.next.maxy, x, y) + this.next.traverse(this.next.minx, this.next.maxy);
                // System.out.println("d found "+x+", "+y+": "+d1 +", "+d2);
                // System.out.println(dist(this.next.maxx, this.next.miny, x, y)+", "+ this.next.traverse(this.next.maxx, this.next.miny));
                // System.out.println(dist(this.next.minx, this.next.maxy, x, y) +", "+ this.next.traverse(this.next.minx, this.next.maxy));
                return Math.min(d1, d2);
            }

            @Override
            public String toString() {
                return "minx:"+this.minx+", maxx:"+this.maxx+", miny:"+this.miny+", maxy:"+this.maxy+", d:"+this.d();
            }
        }

        int dist(int x1, int y1, int x2, int y2){
            return Math.abs(x1-x2)+Math.abs(y1-y2);
        }
    }
}

import java.io.*;
import java.util.*;

public class A{

	static long [][]memo;
	static int dist(int idx,int k1,int k2) {
		return dist(idx,idx+1,k1,k2);
	}
	static int dist(int idx,int idx2,int k1,int k2) {
		int []a=adj[idx].get(k1),b=adj[idx2].get(k2);
		int dx=Math.abs(a[0]-b[0]),dy = Math.abs(a[1]-b[1]);
		return dx+dy;
	}
	static ArrayList<int []>[] adj;
	static long dp(int idx,int state) {

		if(idx==adj.length-1)
			return 0;
		if(memo[state][idx]!=0)
			return memo[state][idx];
		int k1=state==0?0:adj[idx].size()-1;
		int k2=adj[idx+1].size()-1;
		int g=dist(idx+1,idx+1,k2,0);

		long ans=Math.min(dp(idx+1,0)+dist(idx, k1, k2),dp(idx+1,1)+dist(idx,k1,0))+g;
		return memo[state][idx]=ans;

	}
	public static void main(String[] args) throws IOException {
		Scanner sc=new Scanner();
		PrintWriter out=new PrintWriter(System.out);
		int n=sc.nextInt();
		TreeMap<Integer,Integer> map=new TreeMap();
		int []x=new int [n+1],y=new int [n+1];
		for(int i=0;i<=n;i++)
		{
			if(i<n) {
				x[i]=sc.nextInt();
				y[i]=sc.nextInt();
			}

			map.put(Math.max(x[i], y[i]),0);
		}
		int id=0;
		for(int z:map.keySet())
			map.put(z, id++);
		adj=new ArrayList [id];
		for(int i=0;i<id;i++)
			adj[i]=new ArrayList();
		for(int i=0;i<=n;i++) {
			int idx=map.get(Math.max(x[i], y[i]));
			adj[idx].add(new int [] {x[i],y[i]});
		}
		for(int i=0;i<id;i++) {
			Collections.sort(adj[i], (a,b)->(a[0]-a[1]) -(b[0]-b[1]));
		}
		memo=new long [2][id];

		out.println(dp(0,0));
		out.close();
	}
	static class Scanner
	{
		BufferedReader br;
		StringTokenizer st;
		Scanner(){
			br=new BufferedReader(new InputStreamReader(System.in));
		}
		Scanner(String fileName) throws FileNotFoundException{
			br=new BufferedReader(new FileReader(fileName));
		}
		String next() throws IOException {
			while(st==null || !st.hasMoreTokens())
				st=new StringTokenizer(br.readLine());
			return st.nextToken();
		}
		String nextLine() throws IOException {
			return br.readLine();
		}
		int nextInt() throws IOException{
			return Integer.parseInt(next());
		}
		long nextLong()  throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}
		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}
	}
}

import java.awt.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.*;
import java.util.Random;
import java.util.StringTokenizer;

public class Main {

    String fileName = "";
    //////////////////////    SOLUTION   SOLUTION  SOLUTION    //////////////////////////////
    long INF = 1000_000_000_000l;
    int MODULO = 998244353;
    long MAX_VALUE = 1000_000_000_000l;
    int[][] steps = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
    private final static Random rnd = new Random();
    double eps = 1e-1;
    ArrayList<Integer>[] graph;
    class Point{
        long x, y;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
        }
    }
    class Level{
        long l;
        Point closestX, closestY;
        public Level(long l, Point closestX, Point closestY) {
            this.l = l;
            this.closestX = closestX;
            this.closestY = closestY;
        }
    }
    void solve() throws IOException {
        int n = readInt();
        TreeMap<Long, Level> levelMap = new TreeMap<>();
        for (int i=0; i<n; ++i){
            long x = readLong();
            long y = readLong();
            long level = Math.max(x, y);
            if (!levelMap.containsKey(level)) levelMap.put(level, new Level(level, new Point(x, y), new Point(x, y)));
            if (level - y + x < level - levelMap.get(level).closestY.y + levelMap.get(level).closestY.x){
                levelMap.get(level).closestY = new Point(x, y);
            }
            if (y + level - x < level + levelMap.get(level).closestX.y - levelMap.get(level).closestX.x){
                levelMap.get(level).closestX = new Point(x, y);
            }
        }
        levelMap.put(0l, new Level(0, new Point(0, 0), new Point(0, 0)));

        long prevLevelId = 0;
        long prevClosestX = 0;
        long prevClosestY = 0;

        for (int i=0; i < levelMap.size() - 1; ++i){
            long nextLevelId = levelMap.higherKey(prevLevelId);
            Level prevLevel = levelMap.get(prevLevelId);
            Level nextLevel = levelMap.get(nextLevelId);
            Point prevClosestXPoint = prevLevel.closestX;
            Point prevClosestYPoint = prevLevel.closestY;
            Point nextClosestXPoint = nextLevel.closestX;
            Point nextClosestYPoint = nextLevel.closestY;
            long nextClosestX = getDist(nextClosestXPoint, nextClosestYPoint);
            long nextClosestY = getDist(nextClosestXPoint, nextClosestYPoint);

            nextClosestX += Math.min(getDist(prevClosestYPoint, nextClosestYPoint) + prevClosestY, getDist(prevClosestXPoint, nextClosestYPoint) + prevClosestX);
            nextClosestY += Math.min(getDist(prevClosestYPoint, nextClosestXPoint) + prevClosestY, getDist(prevClosestXPoint, nextClosestXPoint) + prevClosestX);

            prevClosestY = nextClosestY;
            prevClosestX = nextClosestX;
            /*out.println(getDist(nextClosestXPoint, nextClosestYPoint));
            out.println(nextClosestX +" "+nextClosestY);
            out.println(nextClosestXPoint.x +" "+nextClosestXPoint.y);
            out.println(nextClosestYPoint.x +" "+nextClosestYPoint.y);
            out.println();*/
            prevLevelId = nextLevelId;
        }

        out.println(Math.min(prevClosestY, prevClosestX));

    }
    long getDist(Point p1, Point p2){
        //out.println(p1.x + " " + p1.y + " " + p2.x +" "+p2.y + " "+(Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y)));
        return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
    }
    class Fenwik {
        long[] t;
        int n;
        Fenwik(int n){
            t = new long[n];
            this.n = n;
        }
        void inc(int r, long new_value){
            for (; r < n; r = r | (r + 1)) t[r] = Math.max(t[r], new_value);
        }

        long getMax(int r){
            long res = 0;
            for (; r >=0; r = (r & (r + 1) ) - 1) res = Math.max(res, t[r]);
            return res;
        }
    }
    boolean isPrime(int n){
        for (int i=2; i*i<=n; ++i){
            if (n%i==0) return false;
        }
        return true;
    }

    class SparseTable{
        int[][] rmq;
        int[] logTable;
        int n;
        SparseTable(int[] a){
            n = a.length;
            logTable = new int[n+1];
            for(int i = 2; i <= n; ++i){
                logTable[i] = logTable[i >> 1] + 1;
            }
            rmq = new int[logTable[n] + 1][n];
            for(int i=0; i<n; ++i){
                rmq[0][i] = a[i];
            }

            for(int k=1; (1 << k) < n; ++k){
                for(int i=0; i + (1 << k) <= n; ++i){
                    int max1 = rmq[k - 1][i];
                    int max2 = rmq[k-1][i + (1 << (k-1))];
                    rmq[k][i] = Math.max(max1, max2);
                }
            }
        }

        int max(int l, int r){
            int k = logTable[r - l];
            int max1 = rmq[k][l];
            int max2 = rmq[k][r - (1 << k) + 1];
            return Math.max(max1, max2);
        }
    }
    long checkBit(long mask, int bit){
        return (mask >> bit) & 1;
    }

    static int checkBit(int mask, int bit) {
        return (mask >> bit) & 1;
    }
    boolean isLower(char c){
        return c >= 'a' && c <= 'z';
    }

    ////////////////////////////////////////////////////////////

    int gcd(int a, int b){
        return b == 0 ? a : gcd(b, a%b);
    }
    long gcd(long a, long b){
        return b == 0 ? a : gcd(b, a%b);
    }
    long binPow(long a, long pow, long MODULO){
        if (pow == 0) return 1;
        if (pow % 2 == 1) {
            return a * binPow(a, pow - 1, MODULO);
        } else {
            long c = binPow(a, pow / 2, MODULO);
            return c * c % MODULO;
        }
    }

    int minInt(int... values) {
        int min = Integer.MAX_VALUE;
        for (int value : values) min = Math.min(min, value);
        return min;
    }

    int maxInt(int... values) {
        int max = Integer.MIN_VALUE;
        for (int value : values) max = Math.max(max, value);
        return max;
    }
    public static void main(String[] args) throws NumberFormatException, IOException {
        // TODO Auto-generated method stub
        new Main().run();
    }

    void run() throws NumberFormatException, IOException {
        solve();
        out.close();
    };

    BufferedReader in;
    PrintWriter out;

    StringTokenizer tok;
    String delim = " ";

    Main() throws FileNotFoundException {
        try {
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        } catch (Exception e) {
            if (fileName.isEmpty()) {
                in = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(System.out);
            } else {
                in = new BufferedReader(new FileReader(fileName + ".in"));
                out = new PrintWriter(fileName + ".out");
            }

        }
        tok = new StringTokenizer("");
    }

    String readLine() throws IOException {
        return in.readLine();
    }

    String readString() throws IOException {
        while (!tok.hasMoreTokens()) {
            String nextLine = readLine();
            if (null == nextLine) {
                return null;
            }

            tok = new StringTokenizer(nextLine);
        }
        return tok.nextToken();
    }

    int readInt() throws NumberFormatException, IOException {
        return Integer.parseInt(readString());
    }
    byte readByte() throws NumberFormatException, IOException {
        return Byte.parseByte(readString());
    }
    int[] readIntArray (int n) throws NumberFormatException, IOException {
        int[] a = new int[n];
        for(int i=0; i<n; ++i){
            a[i] = readInt();
        }
        return a;
    }

    Integer[] readIntegerArray (int n) throws NumberFormatException, IOException {
        Integer[] a = new Integer[n];
        for(int i=0; i<n; ++i){
            a[i] = readInt();
        }
        return a;
    }

    long readLong() throws NumberFormatException, IOException {
        return Long.parseLong(readString());
    }

    double readDouble() throws NumberFormatException, IOException {
        return Double.parseDouble(readString());
    }
}

import java.io.*;
import java.math.BigInteger;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class F_515
{
	public static final long[] POWER2 = generatePOWER2();
	public static final IteratorBuffer<Long> ITERATOR_BUFFER_PRIME = new IteratorBuffer<>(streamPrime(1000000).iterator());
	public static long BIG = 1000000000 + 7;
	private static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
	private static StringTokenizer stringTokenizer = null;
	private static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

	static class Array<Type>
		implements Iterable<Type>
	{
		private final Object[] array;

		public Array(int size)
		{
			this.array = new Object[size];
		}

		public Array(
			int size,
			Type element
		)
		{
			this(size);
			Arrays.fill(
				this.array,
				element
			);
		}

		public Array(
			Array<Type> array,
			Type element
		)
		{
			this(array.size() + 1);
			for (int index = 0; index < array.size(); index++)
			{
				set(
					index,
					array.get(index)
				);
			}
			set(
				size() - 1,
				element
			);
		}

		public Array(List<Type> list)
		{
			this(list.size());
			int index = 0;
			for (Type element : list)
			{
				set(
					index,
					element
				);
				index += 1;
			}
		}

		public Type get(int index)
		{
			return (Type) this.array[index];
		}

		@Override
		public Iterator<Type> iterator()
		{
			return new Iterator<Type>()
			{
				int index = 0;

				@Override
				public boolean hasNext()
				{
					return this.index < size();
				}

				@Override
				public Type next()
				{
					Type result = Array.this.get(index);
					index += 1;
					return result;
				}
			};
		}

		public Array set(
			int index,
			Type value
		)
		{
			this.array[index] = value;
			return this;
		}

		public int size()
		{
			return this.array.length;
		}

		public List<Type> toList()
		{
			List<Type> result = new ArrayList<>();
			for (Type element : this)
			{
				result.add(element);
			}
			return result;
		}

		@Override
		public String toString()
		{
			return "[" + F_515.toString(
				this,
				", "
			) + "]";
		}
	}

	static class BIT
	{
		private static int lastBit(int index)
		{
			return index & -index;
		}

		private final long[] tree;

		public BIT(int size)
		{
			this.tree = new long[size];
		}

		public void add(
			int index,
			long delta
		)
		{
			index += 1;
			while (index <= this.tree.length)
			{
				tree[index - 1] += delta;
				index += lastBit(index);
			}
		}

		public long prefix(int end)
		{
			long result = 0;
			while (end > 0)
			{
				result += this.tree[end - 1];
				end -= lastBit(end);
			}
			return result;
		}

		public int size()
		{
			return this.tree.length;
		}

		public long sum(
			int start,
			int end
		)
		{
			return prefix(end) - prefix(start);
		}
	}

	static abstract class Edge<TypeVertex extends Vertex<TypeVertex, TypeEdge>, TypeEdge extends Edge<TypeVertex, TypeEdge>>
	{
		public final TypeVertex vertex0;
		public final TypeVertex vertex1;
		public final boolean bidirectional;

		public Edge(
			TypeVertex vertex0,
			TypeVertex vertex1,
			boolean bidirectional
		)
		{
			this.vertex0 = vertex0;
			this.vertex1 = vertex1;
			this.bidirectional = bidirectional;
			this.vertex0.edges.add(getThis());
			if (this.bidirectional)
			{
				this.vertex1.edges.add(getThis());
			}
		}

		public abstract TypeEdge getThis();

		public TypeVertex other(Vertex<TypeVertex, TypeEdge> vertex)
		{
			TypeVertex result;
			if (vertex0 == vertex)
			{
				result = vertex1;
			}
			else
			{
				result = vertex0;
			}
			return result;
		}

		public void remove()
		{
			this.vertex0.edges.remove(getThis());
			if (this.bidirectional)
			{
				this.vertex1.edges.remove(getThis());
			}
		}

		@Override
		public String toString()
		{
			return this.vertex0 + "->" + this.vertex1;
		}
	}

	public static class EdgeDefault<TypeVertex extends Vertex<TypeVertex, EdgeDefault<TypeVertex>>>
		extends Edge<TypeVertex, EdgeDefault<TypeVertex>>
	{
		public EdgeDefault(
			TypeVertex vertex0,
			TypeVertex vertex1,
			boolean bidirectional
		)
		{
			super(
				vertex0,
				vertex1,
				bidirectional
			);
		}

		@Override
		public EdgeDefault<TypeVertex> getThis()
		{
			return this;
		}
	}

	public static class EdgeDefaultDefault
		extends Edge<VertexDefaultDefault, EdgeDefaultDefault>
	{
		public EdgeDefaultDefault(
			VertexDefaultDefault vertex0,
			VertexDefaultDefault vertex1,
			boolean bidirectional
		)
		{
			super(
				vertex0,
				vertex1,
				bidirectional
			);
		}

		@Override
		public EdgeDefaultDefault getThis()
		{
			return this;
		}
	}

	public static class FIFO<Type>
	{
		public SingleLinkedList<Type> start;
		public SingleLinkedList<Type> end;

		public FIFO()
		{
			this.start = null;
			this.end = null;
		}

		public boolean isEmpty()
		{
			return this.start == null;
		}

		public Type peek()
		{
			return this.start.element;
		}

		public Type pop()
		{
			Type result = this.start.element;
			this.start = this.start.next;
			return result;
		}

		public void push(Type element)
		{
			SingleLinkedList<Type> list = new SingleLinkedList<>(
				element,
				null
			);
			if (this.start == null)
			{
				this.start = list;
				this.end = list;
			}
			else
			{
				this.end.next = list;
				this.end = list;
			}
		}
	}

	static class Fraction
		implements Comparable<Fraction>
	{
		public static final Fraction ZERO = new Fraction(
			0,
			1
		);

		public static Fraction fraction(long whole)
		{
			return fraction(
				whole,
				1
			);
		}

		public static Fraction fraction(
			long numerator,
			long denominator
		)
		{
			Fraction result;
			if (denominator == 0)
			{
				throw new ArithmeticException();
			}
			if (numerator == 0)
			{
				result = Fraction.ZERO;
			}
			else
			{
				int sign;
				if (numerator < 0 ^ denominator < 0)
				{
					sign = -1;
					numerator = Math.abs(numerator);
					denominator = Math.abs(denominator);
				}
				else
				{
					sign = 1;
				}
				long gcd = gcd(
					numerator,
					denominator
				);
				result = new Fraction(
					sign * numerator / gcd,
					denominator / gcd
				);
			}
			return result;
		}

		public final long numerator;
		public final long denominator;

		private Fraction(
			long numerator,
			long denominator
		)
		{
			this.numerator = numerator;
			this.denominator = denominator;
		}

		public Fraction add(Fraction fraction)
		{
			return fraction(
				this.numerator * fraction.denominator + fraction.numerator * this.denominator,
				this.denominator * fraction.denominator
			);
		}

		@Override
		public int compareTo(Fraction that)
		{
			return Long.compare(
				this.numerator * that.denominator,
				that.numerator * this.denominator
			);
		}

		public Fraction divide(Fraction fraction)
		{
			return multiply(fraction.inverse());
		}

		public boolean equals(Fraction that)
		{
			return this.compareTo(that) == 0;
		}

		public boolean equals(Object that)
		{
			return this.compareTo((Fraction) that) == 0;
		}

		public Fraction getRemainder()
		{
			return fraction(
				this.numerator - getWholePart() * denominator,
				denominator
			);
		}

		public long getWholePart()
		{
			return this.numerator / this.denominator;
		}

		public Fraction inverse()
		{
			return fraction(
				this.denominator,
				this.numerator
			);
		}

		public Fraction multiply(Fraction fraction)
		{
			return fraction(
				this.numerator * fraction.numerator,
				this.denominator * fraction.denominator
			);
		}

		public Fraction neg()
		{
			return fraction(
				-this.numerator,
				this.denominator
			);
		}

		public Fraction sub(Fraction fraction)
		{
			return add(fraction.neg());
		}

		@Override
		public String toString()
		{
			String result;
			if (getRemainder().equals(Fraction.ZERO))
			{
				result = "" + this.numerator;
			}
			else
			{
				result = this.numerator + "/" + this.denominator;
			}
			return result;
		}
	}

	static class IteratorBuffer<Type>
	{
		private Iterator<Type> iterator;
		private List<Type> list;

		public IteratorBuffer(Iterator<Type> iterator)
		{
			this.iterator = iterator;
			this.list = new ArrayList<Type>();
		}

		public Iterator<Type> iterator()
		{
			return new Iterator<Type>()
			{
				int index = 0;

				@Override
				public boolean hasNext()
				{
					return this.index < list.size() || IteratorBuffer.this.iterator.hasNext();
				}

				@Override
				public Type next()
				{
					if (list.size() <= this.index)
					{
						list.add(iterator.next());
					}
					Type result = list.get(index);
					index += 1;
					return result;
				}
			};
		}
	}

	public static class MapCount<Type>
		extends SortedMapAVL<Type, Long>
	{
		private int count;

		public MapCount(Comparator<? super Type> comparator)
		{
			super(comparator);
			this.count = 0;
		}

		public long add(
			Type key,
			Long delta
		)
		{
			long result;
			if (delta > 0)
			{
				Long value = get(key);
				if (value == null)
				{
					value = delta;
				}
				else
				{
					value += delta;
				}
				put(
					key,
					value
				);
				result = delta;
			}
			else
			{
				result = 0;
			}
			this.count += result;
			return result;
		}

		public int count()
		{
			return this.count;
		}

		public List<Type> flatten()
		{
			List<Type> result = new ArrayList<>();
			for (Entry<Type, Long> entry : entrySet())
			{
				for (long index = 0; index < entry.getValue(); index++)
				{
					result.add(entry.getKey());
				}
			}
			return result;
		}

		@Override
		public SortedMapAVL<Type, Long> headMap(Type keyEnd)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public void putAll(Map<? extends Type, ? extends Long> map)
		{
			throw new UnsupportedOperationException();
		}

		public long remove(
			Type key,
			Long delta
		)
		{
			long result;
			if (delta > 0)
			{
				Long value = get(key) - delta;
				if (value <= 0)
				{
					result = delta + value;
					remove(key);
				}
				else
				{
					result = delta;
					put(
						key,
						value
					);
				}
			}
			else
			{
				result = 0;
			}
			this.count -= result;
			return result;
		}

		@Override
		public Long remove(Object key)
		{
			Long result = super.remove(key);
			this.count -= result;
			return result;
		}

		@Override
		public SortedMapAVL<Type, Long> subMap(
			Type keyStart,
			Type keyEnd
		)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public SortedMapAVL<Type, Long> tailMap(Type keyStart)
		{
			throw new UnsupportedOperationException();
		}
	}

	public static class MapSet<TypeKey, TypeValue>
		extends SortedMapAVL<TypeKey, SortedSetAVL<TypeValue>>
		implements Iterable<TypeValue>
	{
		private Comparator<? super TypeValue> comparatorValue;

		public MapSet(
			Comparator<? super TypeKey> comparatorKey,
			Comparator<? super TypeValue> comparatorValue
		)
		{
			super(comparatorKey);
			this.comparatorValue = comparatorValue;
		}

		public MapSet(
			Comparator<? super TypeKey> comparatorKey,
			SortedSetAVL<Entry<TypeKey, SortedSetAVL<TypeValue>>> entrySet,
			Comparator<? super TypeValue> comparatorValue
		)
		{
			super(
				comparatorKey,
				entrySet
			);
			this.comparatorValue = comparatorValue;
		}

		public boolean add(
			TypeKey key,
			TypeValue value
		)
		{
			SortedSetAVL<TypeValue> set = computeIfAbsent(
				key,
				k -> new SortedSetAVL<>(comparatorValue)
			);
			return set.add(value);
		}

		public TypeValue firstValue()
		{
			TypeValue result;
			Entry<TypeKey, SortedSetAVL<TypeValue>> firstEntry = firstEntry();
			if (firstEntry == null)
			{
				result = null;
			}
			else
			{
				result = firstEntry.getValue().first();
			}
			return result;
		}

		@Override
		public MapSet<TypeKey, TypeValue> headMap(TypeKey keyEnd)
		{
			return new MapSet<>(
				this.comparator,
				this.entrySet.headSet(new AbstractMap.SimpleEntry<>(
					keyEnd,
					null
				)),
				this.comparatorValue
			);
		}

		public Iterator<TypeValue> iterator()
		{
			return new Iterator<TypeValue>()
			{
				Iterator<SortedSetAVL<TypeValue>> iteratorValues = values().iterator();
				Iterator<TypeValue> iteratorValue = null;

				@Override
				public boolean hasNext()
				{
					return iteratorValues.hasNext() || (iteratorValue != null && iteratorValue.hasNext());
				}

				@Override
				public TypeValue next()
				{
					if (iteratorValue == null || !iteratorValue.hasNext())
					{
						iteratorValue = iteratorValues.next().iterator();
					}
					return iteratorValue.next();
				}
			};
		}

		public TypeValue lastValue()
		{
			TypeValue result;
			Entry<TypeKey, SortedSetAVL<TypeValue>> lastEntry = lastEntry();
			if (lastEntry == null)
			{
				result = null;
			}
			else
			{
				result = lastEntry.getValue().last();
			}
			return result;
		}

		public boolean removeSet(
			TypeKey key,
			TypeValue value
		)
		{
			boolean result;
			SortedSetAVL<TypeValue> set = get(key);
			if (set == null)
			{
				result = false;
			}
			else
			{
				result = set.remove(value);
				if (set.size() == 0)
				{
					remove(key);
				}
			}
			return result;
		}

		@Override
		public MapSet<TypeKey, TypeValue> tailMap(TypeKey keyStart)
		{
			return new MapSet<>(
				this.comparator,
				this.entrySet.tailSet(new AbstractMap.SimpleEntry<>(
					keyStart,
					null
				)),
				this.comparatorValue
			);
		}
	}

	public static class Matrix
	{
		public final int rows;
		public final int columns;
		public final Fraction[][] cells;

		public Matrix(
			int rows,
			int columns
		)
		{
			this.rows = rows;
			this.columns = columns;
			this.cells = new Fraction[rows][columns];
			for (int row = 0; row < rows; row++)
			{
				for (int column = 0; column < columns; column++)
				{
					set(
						row,
						column,
						Fraction.ZERO
					);
				}
			}
		}

		public void add(
			int rowSource,
			int rowTarget,
			Fraction fraction
		)
		{
			for (int column = 0; column < columns; column++)
			{
				this.cells[rowTarget][column] = this.cells[rowTarget][column].add(this.cells[rowSource][column].multiply(fraction));
			}
		}

		private int columnPivot(int row)
		{
			int result = this.columns;
			for (int column = this.columns - 1; 0 <= column; column--)
			{
				if (this.cells[row][column].compareTo(Fraction.ZERO) != 0)
				{
					result = column;
				}
			}
			return result;
		}

		public void reduce()
		{
			for (int rowMinimum = 0; rowMinimum < this.rows; rowMinimum++)
			{
				int rowPivot = rowPivot(rowMinimum);
				if (rowPivot != -1)
				{
					int columnPivot = columnPivot(rowPivot);
					Fraction current = this.cells[rowMinimum][columnPivot];
					Fraction pivot = this.cells[rowPivot][columnPivot];
					Fraction fraction = pivot.inverse().sub(current.divide(pivot));
					add(
						rowPivot,
						rowMinimum,
						fraction
					);
					for (int row = rowMinimum + 1; row < this.rows; row++)
					{
						if (columnPivot(row) == columnPivot)
						{
							add(
								rowMinimum,
								row,
								this.cells[row][columnPivot(row)].neg()
							);
						}
					}
				}
			}
		}

		private int rowPivot(int rowMinimum)
		{
			int result = -1;
			int pivotColumnMinimum = this.columns;
			for (int row = rowMinimum; row < this.rows; row++)
			{
				int pivotColumn = columnPivot(row);
				if (pivotColumn < pivotColumnMinimum)
				{
					result = row;
					pivotColumnMinimum = pivotColumn;
				}
			}
			return result;
		}

		public void set(
			int row,
			int column,
			Fraction value
		)
		{
			this.cells[row][column] = value;
		}

		public String toString()
		{
			String result = "";
			for (int row = 0; row < rows; row++)
			{
				for (int column = 0; column < columns; column++)
				{
					result += this.cells[row][column] + "\t";
				}
				result += "\n";
			}
			return result;
		}
	}

	public static class Node<Type>
	{
		public static <Type> Node<Type> balance(Node<Type> result)
		{
			while (result != null && 1 < Math.abs(height(result.left) - height(result.right)))
			{
				if (height(result.left) < height(result.right))
				{
					Node<Type> right = result.right;
					if (height(right.right) < height(right.left))
					{
						result = new Node<>(
							result.value,
							result.left,
							right.rotateRight()
						);
					}
					result = result.rotateLeft();
				}
				else
				{
					Node<Type> left = result.left;
					if (height(left.left) < height(left.right))
					{
						result = new Node<>(
							result.value,
							left.rotateLeft(),
							result.right
						);
					}
					result = result.rotateRight();
				}
			}
			return result;
		}

		public static <Type> Node<Type> clone(Node<Type> result)
		{
			if (result != null)
			{
				result = new Node<>(
					result.value,
					clone(result.left),
					clone(result.right)
				);
			}
			return result;
		}

		public static <Type> Node<Type> delete(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					if (node.left == null)
					{
						result = node.right;
					}
					else
					{
						if (node.right == null)
						{
							result = node.left;
						}
						else
						{
							Node<Type> first = first(node.right);
							result = new Node<>(
								first.value,
								node.left,
								delete(
									node.right,
									first.value,
									comparator
								)
							);
						}
					}
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							delete(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							delete(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> Node<Type> first(Node<Type> result)
		{
			while (result.left != null)
			{
				result = result.left;
			}
			return result;
		}

		public static <Type> Node<Type> get(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = node;
				}
				else
				{
					if (compare < 0)
					{
						result = get(
							node.left,
							value,
							comparator
						);
					}
					else
					{
						result = get(
							node.right,
							value,
							comparator
						);
					}
				}
			}
			return result;
		}

		public static <Type> Node<Type> head(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = node.left;
				}
				else
				{
					if (compare < 0)
					{
						result = head(
							node.left,
							value,
							comparator
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							head(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static int height(Node node)
		{
			return node == null ? 0 : node.height;
		}

		public static <Type> Node<Type> insert(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = new Node<>(
					value,
					null,
					null
				);
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = new Node<>(
						value,
						node.left,
						node.right
					);
					;
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							insert(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							insert(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> Node<Type> last(Node<Type> result)
		{
			while (result.right != null)
			{
				result = result.right;
			}
			return result;
		}

		public static int size(Node node)
		{
			return node == null ? 0 : node.size;
		}

		public static <Type> Node<Type> tail(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = new Node<>(
						node.value,
						null,
						node.right
					);
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							tail(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = tail(
							node.right,
							value,
							comparator
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> void traverseOrderIn(
			Node<Type> node,
			Consumer<Type> consumer
		)
		{
			if (node != null)
			{
				traverseOrderIn(
					node.left,
					consumer
				);
				consumer.accept(node.value);
				traverseOrderIn(
					node.right,
					consumer
				);
			}
		}

		public final Type value;
		public final Node<Type> left;
		public final Node<Type> right;
		public final int size;
		private final int height;

		public Node(
			Type value,
			Node<Type> left,
			Node<Type> right
		)
		{
			this.value = value;
			this.left = left;
			this.right = right;
			this.size = 1 + size(left) + size(right);
			this.height = 1 + Math.max(
				height(left),
				height(right)
			);
		}

		public Node<Type> rotateLeft()
		{
			Node<Type> left = new Node<>(
				this.value,
				this.left,
				this.right.left
			);
			return new Node<>(
				this.right.value,
				left,
				this.right.right
			);
		}

		public Node<Type> rotateRight()
		{
			Node<Type> right = new Node<>(
				this.value,
				this.left.right,
				this.right
			);
			return new Node<>(
				this.left.value,
				this.left.left,
				right
			);
		}
	}

	public static class SingleLinkedList<Type>
	{
		public final Type element;
		public SingleLinkedList<Type> next;

		public SingleLinkedList(
			Type element,
			SingleLinkedList<Type> next
		)
		{
			this.element = element;
			this.next = next;
		}

		public void toCollection(Collection<Type> collection)
		{
			if (this.next != null)
			{
				this.next.toCollection(collection);
			}
			collection.add(this.element);
		}
	}

	public static class SmallSetIntegers
	{
		public static final int SIZE = 20;
		public static final int[] SET = generateSet();
		public static final int[] COUNT = generateCount();
		public static final int[] INTEGER = generateInteger();

		private static int count(int set)
		{
			int result = 0;
			for (int integer = 0; integer < SIZE; integer++)
			{
				if (0 < (set & set(integer)))
				{
					result += 1;
				}
			}
			return result;
		}

		private static final int[] generateCount()
		{
			int[] result = new int[1 << SIZE];
			for (int set = 0; set < result.length; set++)
			{
				result[set] = count(set);
			}
			return result;
		}

		private static final int[] generateInteger()
		{
			int[] result = new int[1 << SIZE];
			Arrays.fill(
				result,
				-1
			);
			for (int integer = 0; integer < SIZE; integer++)
			{
				result[SET[integer]] = integer;
			}
			return result;
		}

		private static final int[] generateSet()
		{
			int[] result = new int[SIZE];
			for (int integer = 0; integer < result.length; integer++)
			{
				result[integer] = set(integer);
			}
			return result;
		}

		private static int set(int integer)
		{
			return 1 << integer;
		}
	}

	public static class SortedMapAVL<TypeKey, TypeValue>
		implements SortedMap<TypeKey, TypeValue>
	{
		public final Comparator<? super TypeKey> comparator;
		public final SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet;

		public SortedMapAVL(Comparator<? super TypeKey> comparator)
		{
			this(
				comparator,
				new SortedSetAVL<>((entry0, entry1) -> comparator.compare(
					entry0.getKey(),
					entry1.getKey()
				))
			);
		}

		private SortedMapAVL(
			Comparator<? super TypeKey> comparator,
			SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet
		)
		{
			this.comparator = comparator;
			this.entrySet = entrySet;
		}

		@Override
		public void clear()
		{
			this.entrySet.clear();
		}

		@Override
		public Comparator<? super TypeKey> comparator()
		{
			return this.comparator;
		}

		@Override
		public boolean containsKey(Object key)
		{
			return this.entrySet().contains(new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			));
		}

		@Override
		public boolean containsValue(Object value)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet()
		{
			return this.entrySet;
		}

		public Entry<TypeKey, TypeValue> firstEntry()
		{
			return this.entrySet.first();
		}

		@Override
		public TypeKey firstKey()
		{
			return firstEntry().getKey();
		}

		@Override
		public TypeValue get(Object key)
		{
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			);
			entry = this.entrySet.get(entry);
			return entry == null ? null : entry.getValue();
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> headMap(TypeKey keyEnd)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.headSet(new AbstractMap.SimpleEntry<>(
					keyEnd,
					null
				))
			);
		}

		@Override
		public boolean isEmpty()
		{
			return this.entrySet.isEmpty();
		}

		@Override
		public Set<TypeKey> keySet()
		{
			return new SortedSet<TypeKey>()
			{
				@Override
				public boolean add(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean addAll(Collection<? extends TypeKey> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public void clear()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public Comparator<? super TypeKey> comparator()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean contains(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean containsAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public TypeKey first()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public SortedSet<TypeKey> headSet(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean isEmpty()
				{
					return size() == 0;
				}

				@Override
				public Iterator<TypeKey> iterator()
				{
					final Iterator<Entry<TypeKey, TypeValue>> iterator = SortedMapAVL.this.entrySet.iterator();
					return new Iterator<TypeKey>()
					{
						@Override
						public boolean hasNext()
						{
							return iterator.hasNext();
						}

						@Override
						public TypeKey next()
						{
							return iterator.next().getKey();
						}
					};
				}

				@Override
				public TypeKey last()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean remove(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean removeAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean retainAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public int size()
				{
					return SortedMapAVL.this.entrySet.size();
				}

				@Override
				public SortedSet<TypeKey> subSet(
					TypeKey typeKey,
					TypeKey e1
				)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public SortedSet<TypeKey> tailSet(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public Object[] toArray()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public <T> T[] toArray(T[] ts)
				{
					throw new UnsupportedOperationException();
				}
			};
		}

		public Entry<TypeKey, TypeValue> lastEntry()
		{
			return this.entrySet.last();
		}

		@Override
		public TypeKey lastKey()
		{
			return lastEntry().getKey();
		}

		@Override
		public TypeValue put(
			TypeKey key,
			TypeValue value
		)
		{
			TypeValue result = get(key);
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				key,
				value
			);
			this.entrySet().add(entry);
			return result;
		}

		@Override
		public void putAll(Map<? extends TypeKey, ? extends TypeValue> map)
		{
			map.entrySet()
				.forEach(entry -> put(
					entry.getKey(),
					entry.getValue()
				));
		}

		@Override
		public TypeValue remove(Object key)
		{
			TypeValue result = get(key);
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			);
			this.entrySet.remove(entry);
			return result;
		}

		@Override
		public int size()
		{
			return this.entrySet().size();
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> subMap(
			TypeKey keyStart,
			TypeKey keyEnd
		)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.subSet(
					new AbstractMap.SimpleEntry<>(
						keyStart,
						null
					),
					new AbstractMap.SimpleEntry<>(
						keyEnd,
						null
					)
				)
			);
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> tailMap(TypeKey keyStart)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.tailSet(new AbstractMap.SimpleEntry<>(
					keyStart,
					null
				))
			);
		}

		@Override
		public String toString()
		{
			return this.entrySet().toString();
		}

		@Override
		public Collection<TypeValue> values()
		{
			return new Collection<TypeValue>()
			{
				@Override
				public boolean add(TypeValue typeValue)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean addAll(Collection<? extends TypeValue> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public void clear()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean contains(Object value)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean containsAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean isEmpty()
				{
					return SortedMapAVL.this.entrySet.isEmpty();
				}

				@Override
				public Iterator<TypeValue> iterator()
				{
					return new Iterator<TypeValue>()
					{
						Iterator<Entry<TypeKey, TypeValue>> iterator = SortedMapAVL.this.entrySet.iterator();

						@Override
						public boolean hasNext()
						{
							return this.iterator.hasNext();
						}

						@Override
						public TypeValue next()
						{
							return this.iterator.next().getValue();
						}
					};
				}

				@Override
				public boolean remove(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean removeAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean retainAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public int size()
				{
					return SortedMapAVL.this.entrySet.size();
				}

				@Override
				public Object[] toArray()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public <T> T[] toArray(T[] ts)
				{
					throw new UnsupportedOperationException();
				}
			};
		}
	}

	public static class SortedSetAVL<Type>
		implements SortedSet<Type>
	{
		public Comparator<? super Type> comparator;
		public Node<Type> root;

		private SortedSetAVL(
			Comparator<? super Type> comparator,
			Node<Type> root
		)
		{
			this.comparator = comparator;
			this.root = root;
		}

		public SortedSetAVL(Comparator<? super Type> comparator)
		{
			this(
				comparator,
				null
			);
		}

		public SortedSetAVL(
			Collection<? extends Type> collection,
			Comparator<? super Type> comparator
		)
		{
			this(
				comparator,
				null
			);
			this.addAll(collection);
		}

		public SortedSetAVL(SortedSetAVL<Type> sortedSetAVL)
		{
			this(
				sortedSetAVL.comparator,
				Node.clone(sortedSetAVL.root)
			);
		}

		@Override
		public boolean add(Type value)
		{
			int sizeBefore = size();
			this.root = Node.insert(
				this.root,
				value,
				this.comparator
			);
			return sizeBefore != size();
		}

		@Override
		public boolean addAll(Collection<? extends Type> collection)
		{
			return collection.stream()
				.map(this::add)
				.reduce(
					true,
					(x, y) -> x | y
				);
		}

		@Override
		public void clear()
		{
			this.root = null;
		}

		@Override
		public Comparator<? super Type> comparator()
		{
			return this.comparator;
		}

		@Override
		public boolean contains(Object value)
		{
			return Node.get(
				this.root,
				(Type) value,
				this.comparator
			) != null;
		}

		@Override
		public boolean containsAll(Collection<?> collection)
		{
			return collection.stream()
				.allMatch(this::contains);
		}

		@Override
		public Type first()
		{
			return Node.first(this.root).value;
		}

		public Type get(Type value)
		{
			Node<Type> node = Node.get(
				this.root,
				value,
				this.comparator
			);
			return node == null ? null : node.value;
		}

		@Override
		public SortedSetAVL<Type> headSet(Type valueEnd)
		{
			return new SortedSetAVL<>(
				this.comparator,
				Node.head(
					this.root,
					valueEnd,
					this.comparator
				)
			);
		}

		@Override
		public boolean isEmpty()
		{
			return this.root == null;
		}

		@Override
		public Iterator<Type> iterator()
		{
			Stack<Node<Type>> path = new Stack<>();
			return new Iterator<Type>()
			{
				{
					push(SortedSetAVL.this.root);
				}

				@Override
				public boolean hasNext()
				{
					return !path.isEmpty();
				}

				@Override
				public Type next()
				{
					if (path.isEmpty())
					{
						throw new NoSuchElementException();
					}
					else
					{
						Node<Type> node = path.peek();
						Type result = node.value;
						if (node.right != null)
						{
							push(node.right);
						}
						else
						{
							do
							{
								node = path.pop();
							}
							while (!path.isEmpty() && path.peek().right == node);
						}
						return result;
					}
				}

				public void push(Node<Type> node)
				{
					while (node != null)
					{
						path.push(node);
						node = node.left;
					}
				}
			};
		}

		@Override
		public Type last()
		{
			return Node.last(this.root).value;
		}

		@Override
		public boolean remove(Object value)
		{
			int sizeBefore = size();
			this.root = Node.delete(
				this.root,
				(Type) value,
				this.comparator
			);
			return sizeBefore != size();
		}

		@Override
		public boolean removeAll(Collection<?> collection)
		{
			return collection.stream()
				.map(this::remove)
				.reduce(
					true,
					(x, y) -> x | y
				);
		}

		@Override
		public boolean retainAll(Collection<?> collection)
		{
			SortedSetAVL<Type> set = new SortedSetAVL<>(this.comparator);
			collection.stream()
				.map(element -> (Type) element)
				.filter(this::contains)
				.forEach(set::add);
			boolean result = size() != set.size();
			this.root = set.root;
			return result;
		}

		@Override
		public int size()
		{
			return this.root == null ? 0 : this.root.size;
		}

		@Override
		public SortedSetAVL<Type> subSet(
			Type valueStart,
			Type valueEnd
		)
		{
			return tailSet(valueStart).headSet(valueEnd);
		}

		@Override
		public SortedSetAVL<Type> tailSet(Type valueStart)
		{
			return new SortedSetAVL<>(
				this.comparator,
				Node.tail(
					this.root,
					valueStart,
					this.comparator
				)
			);
		}

		@Override
		public Object[] toArray()
		{
			return toArray(new Object[0]);
		}

		@Override
		public <T> T[] toArray(T[] ts)
		{
			List<Object> list = new ArrayList<>();
			Node.traverseOrderIn(
				this.root,
				list::add
			);
			return list.toArray(ts);
		}

		@Override
		public String toString()
		{
			return "{" + F_515.toString(
				this,
				", "
			) + "}";
		}
	}

	public static class Tree2D
	{
		public static final int SIZE = 1 << 30;
		public static final Tree2D[] TREES_NULL = new Tree2D[] { null, null, null, null };

		public static boolean contains(
			int x,
			int y,
			int left,
			int bottom,
			int size
		)
		{
			return left <= x && x < left + size && bottom <= y && y < bottom + size;
		}

		public static int count(Tree2D[] trees)
		{
			int result = 0;
			for (int index = 0; index < 4; index++)
			{
				if (trees[index] != null)
				{
					result += trees[index].count;
				}
			}
			return result;
		}

		public static int count
			(
				int rectangleLeft,
				int rectangleBottom,
				int rectangleRight,
				int rectangleTop,
				Tree2D tree,
				int left,
				int bottom,
				int size
			)
		{
			int result;
			if (tree == null)
			{
				result = 0;
			}
			else
			{
				int right = left + size;
				int top = bottom + size;
				int intersectionLeft = Math.max(
					rectangleLeft,
					left
				);
				int intersectionBottom = Math.max(
					rectangleBottom,
					bottom
				);
				int intersectionRight = Math.min(
					rectangleRight,
					right
				);
				int intersectionTop = Math.min(
					rectangleTop,
					top
				);
				if (intersectionRight <= intersectionLeft || intersectionTop <= intersectionBottom)
				{
					result = 0;
				}
				else
				{
					if (intersectionLeft == left && intersectionBottom == bottom && intersectionRight == right && intersectionTop == top)
					{
						result = tree.count;
					}
					else
					{
						size = size >> 1;
						result = 0;
						for (int index = 0; index < 4; index++)
						{
							result += count
								(
									rectangleLeft,
									rectangleBottom,
									rectangleRight,
									rectangleTop,
									tree.trees[index],
									quadrantLeft(
										left,
										size,
										index
									),
									quadrantBottom(
										bottom,
										size,
										index
									),
									size
								);
						}
					}
				}
			}
			return result;
		}

		public static int quadrantBottom(
			int bottom,
			int size,
			int index
		)
		{
			return bottom + (index >> 1) * size;
		}

		public static int quadrantLeft(
			int left,
			int size,
			int index
		)
		{
			return left + (index & 1) * size;
		}

		public final Tree2D[] trees;
		public final int count;

		private Tree2D(
			Tree2D[] trees,
			int count
		)
		{
			this.trees = trees;
			this.count = count;
		}

		public Tree2D(Tree2D[] trees)
		{
			this(
				trees,
				count(trees)
			);
		}

		public Tree2D()
		{
			this(TREES_NULL);
		}

		public int count(
			int rectangleLeft,
			int rectangleBottom,
			int rectangleRight,
			int rectangleTop
		)
		{
			return count
				(
					rectangleLeft,
					rectangleBottom,
					rectangleRight,
					rectangleTop,
					this,
					0,
					0,
					SIZE
				);
		}

		public Tree2D setPoint
			(
				int x,
				int y,
				Tree2D tree,
				int left,
				int bottom,
				int size
			)
		{
			Tree2D result;
			if (contains(
				x,
				y,
				left,
				bottom,
				size
			))
			{
				if (size == 1)
				{
					result = new Tree2D(
						TREES_NULL,
						1
					);
				}
				else
				{
					size = size >> 1;
					Tree2D[] trees = new Tree2D[4];
					for (int index = 0; index < 4; index++)
					{
						trees[index] = setPoint
							(
								x,
								y,
								tree == null ? null : tree.trees[index],
								quadrantLeft(
									left,
									size,
									index
								),
								quadrantBottom(
									bottom,
									size,
									index
								),
								size
							);
					}
					result = new Tree2D(trees);
				}
			}
			else
			{
				result = tree;
			}
			return result;
		}

		public Tree2D setPoint(
			int x,
			int y
		)
		{
			return setPoint
				(
					x,
					y,
					this,
					0,
					0,
					SIZE
				);
		}
	}

	public static class Tuple2<Type0, Type1>
	{
		public final Type0 v0;
		public final Type1 v1;

		public Tuple2(
			Type0 v0,
			Type1 v1
		)
		{
			this.v0 = v0;
			this.v1 = v1;
		}

		@Override
		public String toString()
		{
			return "(" + this.v0 + ", " + this.v1 + ")";
		}
	}

	public static class Tuple2Comparable<Type0 extends Comparable<? super Type0>, Type1 extends Comparable<? super Type1>>
		extends Tuple2<Type0, Type1>
		implements Comparable<Tuple2Comparable<Type0, Type1>>
	{
		public Tuple2Comparable(
			Type0 v0,
			Type1 v1
		)
		{
			super(
				v0,
				v1
			);
		}

		@Override
		public int compareTo(Tuple2Comparable<Type0, Type1> that)
		{
			int result = this.v0.compareTo(that.v0);
			if (result == 0)
			{
				result = this.v1.compareTo(that.v1);
			}
			return result;
		}
	}

	public static class Tuple3<Type0, Type1, Type2>
	{
		public final Type0 v0;
		public final Type1 v1;
		public final Type2 v2;

		public Tuple3(
			Type0 v0,
			Type1 v1,
			Type2 v2
		)
		{
			this.v0 = v0;
			this.v1 = v1;
			this.v2 = v2;
		}

		@Override
		public String toString()
		{
			return "(" + this.v0 + ", " + this.v1 + ", " + this.v2 + ")";
		}
	}

	public static class Vertex
		<
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		implements Comparable<Vertex<? super TypeVertex, ? super TypeEdge>>
	{
		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>,
			TypeResult
			> TypeResult breadthFirstSearch
			(
				TypeVertex vertex,
				TypeEdge edge,
				BiFunctionResult<TypeVertex, TypeEdge, TypeResult> function,
				Array<Boolean> visited,
				FIFO<TypeVertex> verticesNext,
				FIFO<TypeEdge> edgesNext,
				TypeResult result
			)
		{
			if (!visited.get(vertex.index))
			{
				visited.set(
					vertex.index,
					true
				);
				result = function.apply(
					vertex,
					edge,
					result
				);
				for (TypeEdge edgeNext : vertex.edges)
				{
					TypeVertex vertexNext = edgeNext.other(vertex);
					if (!visited.get(vertexNext.index))
					{
						verticesNext.push(vertexNext);
						edgesNext.push(edgeNext);
					}
				}
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>,
			TypeResult
			>
		TypeResult breadthFirstSearch
			(
				Array<TypeVertex> vertices,
				int indexVertexStart,
				BiFunctionResult<TypeVertex, TypeEdge, TypeResult> function,
				TypeResult result
			)
		{
			Array<Boolean> visited = new Array<>(
				vertices.size(),
				false
			);
			FIFO<TypeVertex> verticesNext = new FIFO<>();
			verticesNext.push(vertices.get(indexVertexStart));
			FIFO<TypeEdge> edgesNext = new FIFO<>();
			edgesNext.push(null);
			while (!verticesNext.isEmpty())
			{
				result = breadthFirstSearch(
					verticesNext.pop(),
					edgesNext.pop(),
					function,
					visited,
					verticesNext,
					edgesNext,
					result
				);
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		boolean
		cycle
			(
				TypeVertex start,
				SortedSet<TypeVertex> result
			)
		{
			boolean cycle = false;
			Stack<TypeVertex> stackVertex = new Stack<>();
			Stack<TypeEdge> stackEdge = new Stack<>();
			stackVertex.push(start);
			stackEdge.push(null);
			while (!stackVertex.isEmpty())
			{
				TypeVertex vertex = stackVertex.pop();
				TypeEdge edge = stackEdge.pop();
				if (!result.contains(vertex))
				{
					result.add(vertex);
					for (TypeEdge otherEdge : vertex.edges)
					{
						if (otherEdge != edge)
						{
							TypeVertex otherVertex = otherEdge.other(vertex);
							if (result.contains(otherVertex))
							{
								cycle = true;
							}
							else
							{
								stackVertex.push(otherVertex);
								stackEdge.push(otherEdge);
							}
						}
					}
				}
			}
			return cycle;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		SortedSet<TypeVertex>
		depthFirstSearch
			(
				TypeVertex start,
				BiConsumer<TypeVertex, TypeEdge> functionVisitPre,
				BiConsumer<TypeVertex, TypeEdge> functionVisitPost
			)
		{
			SortedSet<TypeVertex> result = new SortedSetAVL<>(Comparator.naturalOrder());
			Stack<TypeVertex> stackVertex = new Stack<>();
			Stack<TypeEdge> stackEdge = new Stack<>();
			stackVertex.push(start);
			stackEdge.push(null);
			while (!stackVertex.isEmpty())
			{
				TypeVertex vertex = stackVertex.pop();
				TypeEdge edge = stackEdge.pop();
				if (result.contains(vertex))
				{
					functionVisitPost.accept(
						vertex,
						edge
					);
				}
				else
				{
					result.add(vertex);
					stackVertex.push(vertex);
					stackEdge.push(edge);
					functionVisitPre.accept(
						vertex,
						edge
					);
					for (TypeEdge otherEdge : vertex.edges)
					{
						TypeVertex otherVertex = otherEdge.other(vertex);
						if (!result.contains(otherVertex))
						{
							stackVertex.push(otherVertex);
							stackEdge.push(otherEdge);
						}
					}
				}
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		SortedSet<TypeVertex>
		depthFirstSearch
			(
				TypeVertex start,
				Consumer<TypeVertex> functionVisitPreVertex,
				Consumer<TypeVertex> functionVisitPostVertex
			)
		{
			BiConsumer<TypeVertex, TypeEdge> functionVisitPreVertexEdge = (vertex, edge) ->
			{
				functionVisitPreVertex.accept(vertex);
			};
			BiConsumer<TypeVertex, TypeEdge> functionVisitPostVertexEdge = (vertex, edge) ->
			{
				functionVisitPostVertex.accept(vertex);
			};
			return depthFirstSearch(
				start,
				functionVisitPreVertexEdge,
				functionVisitPostVertexEdge
			);
		}

		public final int index;
		public final List<TypeEdge> edges;

		public Vertex(int index)
		{
			this.index = index;
			this.edges = new ArrayList<>();
		}

		@Override
		public int compareTo(Vertex<? super TypeVertex, ? super TypeEdge> that)
		{
			return Integer.compare(
				this.index,
				that.index
			);
		}

		@Override
		public String toString()
		{
			return "" + this.index;
		}
	}

	public static class VertexDefault<TypeEdge extends Edge<VertexDefault<TypeEdge>, TypeEdge>>
		extends Vertex<VertexDefault<TypeEdge>, TypeEdge>
	{
		public VertexDefault(int index)
		{
			super(index);
		}
	}

	public static class VertexDefaultDefault
		extends Vertex<VertexDefaultDefault, EdgeDefaultDefault>
	{
		public static Array<VertexDefaultDefault> vertices(int n)
		{
			Array<VertexDefaultDefault> result = new Array<>(n);
			for (int index = 0; index < n; index++)
			{
				result.set(
					index,
					new VertexDefaultDefault(index)
				);
			}
			return result;
		}

		public VertexDefaultDefault(int index)
		{
			super(index);
		}
	}

	public static class Wrapper<Type>
	{
		public Type value;

		public Wrapper(Type value)
		{
			this.value = value;
		}

		public Type get()
		{
			return this.value;
		}

		public void set(Type value)
		{
			this.value = value;
		}

		@Override
		public String toString()
		{
			return this.value.toString();
		}
	}

	public static void add(
		int delta,
		int[] result
	)
	{
		for (int index = 0; index < result.length; index++)
		{
			result[index] += delta;
		}
	}

	public static void add(
		int delta,
		int[]... result
	)
	{
		for (int index = 0; index < result.length; index++)
		{
			add(
				delta,
				result[index]
			);
		}
	}

	public static long add(
		long x,
		long y
	)
	{
		return (x + y) % BIG;
	}

	public static int binarySearchMaximum(
		Function<Integer, Boolean> filter,
		int start,
		int end
	)
	{
		return -binarySearchMinimum(
			x -> filter.apply(-x),
			-end,
			-start
		);
	}

	public static int binarySearchMinimum(
		Function<Integer, Boolean> filter,
		int start,
		int end
	)
	{
		int result;
		if (start == end)
		{
			result = end;
		}
		else
		{
			int middle = start + (end - start) / 2;
			if (filter.apply(middle))
			{
				result = binarySearchMinimum(
					filter,
					start,
					middle
				);
			}
			else
			{
				result = binarySearchMinimum(
					filter,
					middle + 1,
					end
				);
			}
		}
		return result;
	}

	public static void close()
	{
		out.close();
	}

	private static void combinations(
		int n,
		int k,
		int start,
		SortedSet<Integer> combination,
		List<SortedSet<Integer>> result
	)
	{
		if (k == 0)
		{
			result.add(new SortedSetAVL<>(
				combination,
				Comparator.naturalOrder()
			));
		}
		else
		{
			for (int index = start; index < n; index++)
			{
				if (!combination.contains(index))
				{
					combination.add(index);
					combinations(
						n,
						k - 1,
						index + 1,
						combination,
						result
					);
					combination.remove(index);
				}
			}
		}
	}

	public static List<SortedSet<Integer>> combinations(
		int n,
		int k
	)
	{
		List<SortedSet<Integer>> result = new ArrayList<>();
		combinations(
			n,
			k,
			0,
			new SortedSetAVL<>(Comparator.naturalOrder()),
			result
		);
		return result;
	}

	public static <Type> int compare(
		Iterator<Type> iterator0,
		Iterator<Type> iterator1,
		Comparator<Type> comparator
	)
	{
		int result = 0;
		while (result == 0 && iterator0.hasNext() && iterator1.hasNext())
		{
			result = comparator.compare(
				iterator0.next(),
				iterator1.next()
			);
		}
		if (result == 0)
		{
			if (iterator1.hasNext())
			{
				result = -1;
			}
			else
			{
				if (iterator0.hasNext())
				{
					result = 1;
				}
			}
		}
		return result;
	}

	public static <Type> int compare(
		Iterable<Type> iterable0,
		Iterable<Type> iterable1,
		Comparator<Type> comparator
	)
	{
		return compare(
			iterable0.iterator(),
			iterable1.iterator(),
			comparator
		);
	}

	public static long divideCeil(
		long x,
		long y
	)
	{
		return (x + y - 1) / y;
	}

	public static Set<Long> divisors(long n)
	{
		SortedSetAVL<Long> result = new SortedSetAVL<>(Comparator.naturalOrder());
		result.add(1L);
		for (Long factor : factors(n))
		{
			SortedSetAVL<Long> divisors = new SortedSetAVL<>(result);
			for (Long divisor : result)
			{
				divisors.add(divisor * factor);
			}
			result = divisors;
		}
		return result;
	}

	public static LinkedList<Long> factors(long n)
	{
		LinkedList<Long> result = new LinkedList<>();
		Iterator<Long> primes = ITERATOR_BUFFER_PRIME.iterator();
		Long prime;
		while (n > 1 && (prime = primes.next()) * prime <= n)
		{
			while (n % prime == 0)
			{
				result.add(prime);
				n /= prime;
			}
		}
		if (n > 1)
		{
			result.add(n);
		}
		return result;
	}

	public static long faculty(int n)
	{
		long result = 1;
		for (int index = 2; index <= n; index++)
		{
			result *= index;
		}
		return result;
	}

	static long gcd(
		long a,
		long b
	)
	{
		return b == 0 ? a : gcd(
			b,
			a % b
		);
	}

	public static long[] generatePOWER2()
	{
		long[] result = new long[63];
		for (int x = 0; x < result.length; x++)
		{
			result[x] = 1L << x;
		}
		return result;
	}

	public static boolean isPrime(long x)
	{
		boolean result = x > 1;
		Iterator<Long> iterator = ITERATOR_BUFFER_PRIME.iterator();
		Long prime;
		while ((prime = iterator.next()) * prime <= x)
		{
			result &= x % prime > 0;
		}
		return result;
	}

	public static long knapsack(
		List<Tuple3<Long, Integer, Integer>> itemsValueWeightCount,
		int weightMaximum
	)
	{
		long[] valuesMaximum = new long[weightMaximum + 1];
		for (Tuple3<Long, Integer, Integer> itemValueWeightCount : itemsValueWeightCount)
		{
			long itemValue = itemValueWeightCount.v0;
			int itemWeight = itemValueWeightCount.v1;
			int itemCount = itemValueWeightCount.v2;
			for (int weight = weightMaximum; 0 <= weight; weight--)
			{
				for (int index = 1; index <= itemCount && 0 <= weight - index * itemWeight; index++)
				{
					valuesMaximum[weight] = Math.max(
						valuesMaximum[weight],
						valuesMaximum[weight - index * itemWeight] + index * itemValue
					);
				}
			}
		}
		long result = 0;
		for (long valueMaximum : valuesMaximum)
		{
			result = Math.max(
				result,
				valueMaximum
			);
		}
		return result;
	}

	public static boolean knapsackPossible(
		List<Tuple2<Integer, Integer>> itemsWeightCount,
		int weightMaximum
	)
	{
		boolean[] weightPossible = new boolean[weightMaximum + 1];
		weightPossible[0] = true;
		int weightLargest = 0;
		for (Tuple2<Integer, Integer> itemWeightCount : itemsWeightCount)
		{
			int itemWeight = itemWeightCount.v0;
			int itemCount = itemWeightCount.v1;
			for (int weightStart = 0; weightStart < itemWeight; weightStart++)
			{
				int count = 0;
				for (int weight = weightStart; weight <= weightMaximum && (0 < count || weight <= weightLargest); weight += itemWeight)
				{
					if (weightPossible[weight])
					{
						count = itemCount;
					}
					else
					{
						if (0 < count)
						{
							weightPossible[weight] = true;
							weightLargest = weight;
							count -= 1;
						}
					}
				}
			}
		}
		return weightPossible[weightMaximum];
	}

	public static long lcm(
		int a,
		int b
	)
	{
		return a * b / gcd(
			a,
			b
		);
	}

	public static void main(String[] args)
	{
		try
		{
			solve();
		}
		catch (IOException exception)
		{
			exception.printStackTrace();
		}
		close();
	}

	public static long mul(
		long x,
		long y
	)
	{
		return (x * y) % BIG;
	}

	public static double nextDouble()
		throws IOException
	{
		return Double.parseDouble(nextString());
	}

	public static int nextInt()
		throws IOException
	{
		return Integer.parseInt(nextString());
	}

	public static void nextInts(
		int n,
		int[]... result
	)
		throws IOException
	{
		for (int index = 0; index < n; index++)
		{
			for (int value = 0; value < result.length; value++)
			{
				result[value][index] = nextInt();
			}
		}
	}

	public static int[] nextInts(int n)
		throws IOException
	{
		int[] result = new int[n];
		nextInts(
			n,
			result
		);
		return result;
	}

	public static String nextLine()
		throws IOException
	{
		return bufferedReader.readLine();
	}

	public static long nextLong()
		throws IOException
	{
		return Long.parseLong(nextString());
	}

	public static void nextLongs(
		int n,
		long[]... result
	)
		throws IOException
	{
		for (int index = 0; index < n; index++)
		{
			for (int value = 0; value < result.length; value++)
			{
				result[value][index] = nextLong();
			}
		}
	}

	public static long[] nextLongs(int n)
		throws IOException
	{
		long[] result = new long[n];
		nextLongs(
			n,
			result
		);
		return result;
	}

	public static String nextString()
		throws IOException
	{
		while ((stringTokenizer == null) || (!stringTokenizer.hasMoreTokens()))
		{
			stringTokenizer = new StringTokenizer(bufferedReader.readLine());
		}
		return stringTokenizer.nextToken();
	}

	public static String[] nextStrings(int n)
		throws IOException
	{
		String[] result = new String[n];
		{
			for (int index = 0; index < n; index++)
			{
				result[index] = nextString();
			}
		}
		return result;
	}

	public static <T> List<T> permutation(
		long p,
		List<T> x
	)
	{
		List<T> copy = new ArrayList<>();
		for (int index = 0; index < x.size(); index++)
		{
			copy.add(x.get(index));
		}
		List<T> result = new ArrayList<>();
		for (int indexTo = 0; indexTo < x.size(); indexTo++)
		{
			int indexFrom = (int) p % copy.size();
			p = p / copy.size();
			result.add(copy.remove(indexFrom));
		}
		return result;
	}

	public static <Type> List<List<Type>> permutations(List<Type> list)
	{
		List<List<Type>> result = new ArrayList<>();
		result.add(new ArrayList<>());
		for (Type element : list)
		{
			List<List<Type>> permutations = result;
			result = new ArrayList<>();
			for (List<Type> permutation : permutations)
			{
				for (int index = 0; index <= permutation.size(); index++)
				{
					List<Type> permutationNew = new ArrayList<>(permutation);
					permutationNew.add(
						index,
						element
					);
					result.add(permutationNew);
				}
			}
		}
		return result;
	}

	public static long[][] sizeGroup2CombinationsCount(int maximum)
	{
		long[][] result = new long[maximum + 1][maximum + 1];
		for (int length = 0; length <= maximum; length++)
		{
			result[length][0] = 1;
			for (int group = 1; group <= length; group++)
			{
				result[length][group] = add(
					result[length - 1][group - 1],
					result[length - 1][group]
				);
			}
		}
		return result;
	}

	public static Stream<BigInteger> streamFibonacci()
	{
		return Stream.generate(new Supplier<BigInteger>()
		{
			private BigInteger n0 = BigInteger.ZERO;
			private BigInteger n1 = BigInteger.ONE;

			@Override
			public BigInteger get()
			{
				BigInteger result = n0;
				n0 = n1;
				n1 = result.add(n0);
				return result;
			}
		});
	}

	public static Stream<Long> streamPrime(int sieveSize)
	{
		return Stream.generate(new Supplier<Long>()
		{
			private boolean[] isPrime = new boolean[sieveSize];
			private long sieveOffset = 2;
			private List<Long> primes = new ArrayList<>();
			private int index = 0;

			public void filter(
				long prime,
				boolean[] result
			)
			{
				if (prime * prime < this.sieveOffset + sieveSize)
				{
					long remainingStart = this.sieveOffset % prime;
					long start = remainingStart == 0 ? 0 : prime - remainingStart;
					for (long index = start; index < sieveSize; index += prime)
					{
						result[(int) index] = false;
					}
				}
			}

			public void generatePrimes()
			{
				Arrays.fill(
					this.isPrime,
					true
				);
				this.primes.forEach(prime -> filter(
					prime,
					isPrime
				));
				for (int index = 0; index < sieveSize; index++)
				{
					if (isPrime[index])
					{
						this.primes.add(this.sieveOffset + index);
						filter(
							this.sieveOffset + index,
							isPrime
						);
					}
				}
				this.sieveOffset += sieveSize;
			}

			@Override
			public Long get()
			{
				while (this.primes.size() <= this.index)
				{
					generatePrimes();
				}
				Long result = this.primes.get(this.index);
				this.index += 1;
				return result;
			}
		});
	}

	public static <Type> String toString(
		Iterator<Type> iterator,
		String separator
	)
	{
		StringBuilder stringBuilder = new StringBuilder();
		if (iterator.hasNext())
		{
			stringBuilder.append(iterator.next());
		}
		while (iterator.hasNext())
		{
			stringBuilder.append(separator);
			stringBuilder.append(iterator.next());
		}
		return stringBuilder.toString();
	}

	public static <Type> String toString(Iterator<Type> iterator)
	{
		return toString(
			iterator,
			" "
		);
	}

	public static <Type> String toString(
		Iterable<Type> iterable,
		String separator
	)
	{
		return toString(
			iterable.iterator(),
			separator
		);
	}

	public static <Type> String toString(Iterable<Type> iterable)
	{
		return toString(
			iterable,
			" "
		);
	}

	public static long totient(long n)
	{
		Set<Long> factors = new SortedSetAVL<>(
			factors(n),
			Comparator.naturalOrder()
		);
		long result = n;
		for (long p : factors)
		{
			result -= result / p;
		}
		return result;
	}

	interface BiFunctionResult<Type0, Type1, TypeResult>
	{
		TypeResult apply(
			Type0 x0,
			Type1 x1,
			TypeResult x2
		);
	}

	static class Point
		implements Comparable<Point>
	{
		public final int x;
		public final int y;

		@Override
		public int compareTo(Point that)
		{
			int result = Integer.compare(
				this.x,
				that.x
			);
			if (result == 0)
			{
				result = Integer.compare(
					this.y,
					that.y
				);
			}
			return result;
		}

		public Point(
			int x,
			int y
		)
		{
			this.x = x;
			this.y = y;
		}

		public int level()
		{
			return Math.max(
				this.x,
				this.y
			);
		}

		public long distance(Point point)
		{
			return Math.abs(this.x - point.x) + Math.abs(this.y - point.y);
		}

		public String toString()
		{
			return "(" + this.x + ", " + this.y + ")";
		}
	}

	public static Point min
		(
			Set<Point> points,
			Function<Point, Integer> function1,
			Function<Point, Integer> function2
		)
	{
		Iterator<Point> iterator = points.iterator();
		Point result = iterator.next();
		while (iterator.hasNext())
		{
			Point point = iterator.next();
			if (function1.apply(point) < function1.apply(result))
			{
				result = point;
			}
			else
			{
				if (function1.apply(point).longValue() == function1.apply(result).longValue() && function2.apply(point) < function2.apply(result))
				{
					result = point;
				}
			}
		}
		return result;
	}

	public static long solve(Point[] pointsArray)
	{
		MapSet<Integer, Point> level2Points = new MapSet<>(
			Comparator.naturalOrder(),
			Comparator.naturalOrder()
		);
		for (int index = 0; index < pointsArray.length; index++)
		{
			level2Points.add(
				pointsArray[index].level(),
				pointsArray[index]
			);
		}
		long resultLeft = 0;
		long resultDown = 0;
		Point lastLeft = new Point(
			0,
			0
		);
		Point lastDown = new Point(
			0,
			0
		);
		for (Map.Entry<Integer, SortedSetAVL<Point>> entry : level2Points.entrySet)
		{
			Set<Point> points = entry.getValue();
			Point left = min
				(
					points,
					point -> point.x,
					point -> -point.y
				);
			Point down = min
				(
					points,
					point -> point.y,
					point -> -point.x
				);
			long distanceLevel = down.distance(left);
			long resultLeftNew = Math.min
				(
					resultLeft + lastLeft.distance(down),
					resultDown + lastDown.distance(down)
				) + distanceLevel;
			long resultDownNew = Math.min
				(
					resultLeft + lastLeft.distance(left),
					resultDown + lastDown.distance(left)
				) + distanceLevel;
			resultLeft = resultLeftNew;
			resultDown = resultDownNew;
			lastLeft = left;
			lastDown = down;
		}
		return Math.min
			(
				resultDown,
				resultLeft
			);
	}

	public static void solve()
		throws IOException
	{
		int n = nextInt();
		Point[] points = new Point[n];
		for (int index = 0; index < n; index++)
		{
			Point point = new Point
				(
					nextInt(),
					nextInt()
				);
			points[index] = point;
		}
		out.println(solve(points));
	}
}

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;

public class ProblemF {

    static class Point {
        long x;
        long y;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Map<Long, Point> left = new TreeMap<>();
        Map<Long, Point> right = new TreeMap<>();
        for(int i=0;i<n;i++) {
            long x = sc.nextInt();
            long y = sc.nextInt();
            long l = Math.max(x, y);
            if(!left.containsKey(l)) {
                left.put(l, new Point(x, y));
            } else if(left.get(l).x > x){
                left.put(l, new Point(x, y));
            } else if(left.get(l).x == x){
                left.put(l, new Point(x, Math.max(y, left.get(l).y)));
            }
            if(!right.containsKey(l)) {
                right.put(l, new Point(x, y));
            } else if(right.get(l).y > y) {
                right.put(l, new Point(x, y));
            } else if(right.get(l).y == y){
                right.put(l, new Point(Math.max(right.get(l).x, x), y));
            }
//            System.out.println("Left " + left.get(l).x + " " + left.get(l).y);
//            System.out.println("Right " + right.get(l).x + " " + right.get(l).y);
        }
        long lans = 0;
        long plans = 0;
        long rans = 0;
        long prans = 0;
        Point pvsl = new Point(0, 0);
        Point pvsr = new Point(0, 0);
        for(Map.Entry<Long, Point> e: left.entrySet()) {
            Point lp = left.get(e.getKey());
            Point rp = right.get(e.getKey());
//            System.out.println(lp.x + " " + lp.y + " " + rp.x + " " + rp.y);
            rans = dist(lp, rp) + Math.min(plans + dist(lp, pvsl), prans + dist(lp, pvsr));
            lans = dist(lp, rp) + Math.min(plans + dist(rp, pvsl), prans + dist(rp, pvsr));
//            System.out.println(lans + " " + rans);
            pvsl = lp;
            pvsr = rp;
            plans = lans;
            prans = rans;
        }
        System.out.println(Math.min(lans, rans));
    }

    public static long dist(Point p1, Point p2) {
        return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
    }

}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Vector;
import java.util.Scanner;
import java.util.Comparator;
import java.util.Collections;
import java.util.ArrayList;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author xwchen
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskF solver = new TaskF();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskF {
        public void solve(int testNumber, Scanner in, PrintWriter out) {

            int n = in.nextInt();

            ArrayList<Point> points = new ArrayList<Point>();

            for (int i = 0; i < n; ++i) {
                int x = in.nextInt();
                int y = in.nextInt();
                points.add(new Point(x, y));
            }
            Collections.sort(points, new Comparator<Point>() {

                public int compare(Point o1, Point o2) {
                    int mx1 = Math.max(o1.x, o1.y);
                    int mx2 = Math.max(o2.x, o2.y);
                    if (mx1 != mx2) {
                        return mx1 - mx2;
                    } else {
                        if (o1.x < o2.x) {
                            return -1;
                        } else if (o1.y > o2.y) {
                            return -1;
                        } else {
                            return 1;
                        }
                    }
                }
            });

            Vector<Integer> left = new Vector<Integer>();
            Vector<Integer> right = new Vector<Integer>();
            int last = 0;

            for (int i = 0; i < n; ++i) {
                int mx = Math.max(points.get(i).x, points.get(i).y);
                if (mx == last) {
                    right.set(right.size() - 1, i);
                } else {
                    left.add(i);
                    right.add(i);
                    last = mx;
                }
            }
            int m = left.size();
            long res = 0;
            Point st = new Point(0, 0);
            long dd = dis(points.get(left.get(0)), points.get(right.get(0)));
            long ll = dd + dis(st, points.get(right.get(0)));
            long rr = dd + dis(st, points.get(left.get(0)));

            for (int i = 1; i < m; ++i) {
                dd = dis(points.get(left.get(i)), points.get(right.get(i)));
                long nl = dd + Math.min(dis(points.get(left.get(i - 1)), points.get(right.get(i))) + ll, dis(points.get(right.get(i - 1)), points.get(right.get(i))) + rr);
                long nr = dd + Math.min(dis(points.get(left.get(i - 1)), points.get(left.get(i))) + ll, dis(points.get(right.get(i - 1)), points.get(left.get(i))) + rr);
                ll = nl;
                rr = nr;
            }
            out.println(Math.min(ll, rr));
        }

        int dis(Point a, Point b) {
            return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
        }

        class Point {
            public int x;
            public int y;

            Point(int x, int y) {
                this.x = x;
                this.y = y;
            }

        }

    }
}

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringTokenizer;

import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.round;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;
import static java.util.Collections.reverseOrder;
import static java.util.Collections.sort;
import static java.util.Comparator.comparing;

public class Main {
    FastScanner in;
    PrintWriter out;

    class Point {
        int x, y, max;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
            max = max(x, y);
        }
    }

    long dist(Point a, Point b) {
        return abs(a.x - b.x) + abs(a.y - b.y);
    }

    private void solve() throws IOException {
        int n = in.nextInt();
        Point[] p = new Point[n];
        for (int i = 0; i < n; i++)
            p[i] = new Point(in.nextInt(), in.nextInt());

        sort(p, (o1, o2) -> o1.max != o2.max ? o1.max - o2.max : o1.x != o2.x ? o1.x - o2.x : o2.y - o1.y);

        long[] dist = new long[2];
        long pd;
        Point[] last = new Point[]{new Point(0, 0), new Point(0, 0)};
        for (int l = 0, r = 0; l < n; l = r) {
            while (r < n && p[r].max == p[l].max)
                r++;

            pd = dist[0];
            dist[0] = min(dist[0] + dist(last[0], p[r - 1]), dist[1] + dist(last[1], p[r - 1])) + dist(p[l], p[r - 1]);
            dist[1] = min(pd + dist(last[0], p[l]), dist[1] + dist(last[1], p[l])) + dist(p[l], p[r - 1]);
            last[0] = p[l];
            last[1] = p[r - 1];
        }
        out.println(min(dist[0], dist[1]));
    }

    class FastScanner {
        StringTokenizer st;
        BufferedReader br;

        FastScanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        boolean hasNext() throws IOException {
            return br.ready() || (st != null && st.hasMoreTokens());
        }

        int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        String nextLine() throws IOException {
            return br.readLine();
        }

        boolean hasNextLine() throws IOException {
            return br.ready();
        }
    }

    private void run() throws IOException {
        in = new FastScanner(System.in); // new FastScanner(new FileInputStream("input.txt"));
        out = new PrintWriter(System.out); // new PrintWriter(new FileOutputStream("output.txt"));

        solve();

        out.flush();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new Main().run();
    }
}

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringTokenizer;

import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.round;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;
import static java.util.Collections.reverseOrder;
import static java.util.Collections.sort;
import static java.util.Comparator.comparing;

public class Main {
    FastScanner in;
    PrintWriter out;

    class Point {
        int x, y, max;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
            max = max(x, y);
        }
    }

    long dist(Point a, Point b) {
        return abs(a.x - b.x) + abs(a.y - b.y);
    }

    private void solve() throws IOException {
        int n = in.nextInt();
        Point[] p = new Point[n];
        for (int i = 0; i < n; i++)
            p[i] = new Point(in.nextInt(), in.nextInt());

        sort(p, (o1, o2) -> o1.max != o2.max ? o1.max - o2.max : o1.x != o2.x ? o1.x - o2.x : o2.y - o1.y);

        long[] dist = new long[2];
        long pd;
        Point[] last = new Point[]{new Point(0, 0), new Point(0, 0)};
        for (int l = 0, r = 0; l < n; l = r) {
            while (r < n && p[r].max == p[l].max)
                r++; //

            pd = dist[0];
            dist[0] = min(dist[0] + dist(last[0], p[r - 1]), dist[1] + dist(last[1], p[r - 1])) + dist(p[l], p[r - 1]);
            dist[1] = min(pd + dist(last[0], p[l]), dist[1] + dist(last[1], p[l])) + dist(p[l], p[r - 1]);
            last[0] = p[l];
            last[1] = p[r - 1];
        }
        out.println(min(dist[0], dist[1]));
    }

    class FastScanner {
        StringTokenizer st;
        BufferedReader br;

        FastScanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        boolean hasNext() throws IOException {
            return br.ready() || (st != null && st.hasMoreTokens());
        }

        int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        String nextLine() throws IOException {
            return br.readLine();
        }

        boolean hasNextLine() throws IOException {
            return br.ready();
        }
    }

    private void run() throws IOException {
        in = new FastScanner(System.in); // new FastScanner(new FileInputStream("input.txt"));
        out = new PrintWriter(System.out); // new PrintWriter(new FileOutputStream("output.txt"));

        solve();

        out.flush();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new Main().run();
    }
}

/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main
{
    static Reader scan;
    static PrintWriter pw;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<25)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static void solve() throws IOException
    {
        scan = new Reader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        int n = ni();
        TreeMap<Integer, Pair> leftmost = new TreeMap<>();
        TreeMap<Integer, Pair> downmost = new TreeMap<>();
        ArrayList<Integer> levels = new ArrayList<>();
        for(int i=0;i<n;++i) {
            int x = ni(), y = ni();
            int lev = max(x,y);
            if(!leftmost.containsKey(lev)) {
                leftmost.put(lev, new Pair(x,y));
            }
            else {
                Pair p = leftmost.get(lev);
                if(x<p.x) {
                    leftmost.put(lev, new Pair(x,y));
                }
                else if(x==lev && y>p.y) {
                    leftmost.put(lev, new Pair(x,y));
                }
            }
            if(!downmost.containsKey(lev)) {
                downmost.put(lev, new Pair(x,y));
            }
            else {
                Pair p = downmost.get(lev);
                if(x>p.x) {
                    downmost.put(lev, new Pair(x,y));
                }
                else if(x==lev && y<p.y) {
                    downmost.put(lev, new Pair(x,y));
                }
            }
        }
        //pl(downmost);
        //pl(leftmost);
        for(int e:leftmost.keySet()) {
            levels.add(e);
        }
        Collections.sort(levels);
        //pa("levels", levels);
        int N = levels.size();
        long dp[][] = new long[N][2];  //0 left, 1 down
        int highest_level = levels.get(N-1);
        dp[N-1][0] = dp[N-1][1] = dis(leftmost.get(highest_level), downmost.get(highest_level));
        for(int i=N-2;i>=0;--i) {
            int lev = levels.get(i);
            int nxtlev = levels.get(i+1);
            Pair foo = leftmost.get(lev);
            Pair bar = downmost.get(lev);
            long travel = dis(foo, bar);
            //pl("i : "+i+" travel : "+travel+" lev : "+lev);
            dp[i][0] = travel + min(dis(downmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1], dis(downmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0]);
            dp[i][1] = travel + min(dis(leftmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0], dis(leftmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1]);
        }
        //pa("DP", dp);
        long ans = min(dis(new Pair(0,0), leftmost.get(levels.get(0))) + dp[0][0], dis(new Pair(0,0), downmost.get(levels.get(0))) + dp[0][1]);
        pl(ans);
        pw.flush();
        pw.close();
    }
    static long dis(Pair p, Pair q) {
        return abs(p.x-q.x) + abs(p.y-q.y);
    }
    static class Pair implements Comparable<Pair>
    {
        int x,y;
        Pair(int x,int y)
        {
            this.x=x;
            this.y=y;
        }
        public int compareTo(Pair other)
        {
            if(this.x!=other.x)
                return this.x-other.x;
            return this.y-other.y;
        }
        public String toString()
        {
            return "("+x+","+y+")";
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[64];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}

import java.io.*;
import java.util.*;
import java.math.*;
import java.lang.*;

import static java.lang.Math.*;

public class Main implements Runnable {
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private SpaceCharFilter filter;
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars==-1)
                throw new InputMismatchException();

            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                }
                catch (IOException e) {
                    throw new InputMismatchException();
                }

                if(numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
        public int nextInt() {
            int c = read();

            while(isSpaceChar(c))
                c = read();

            int sgn = 1;

            if (c == '-') {
                sgn = -1;
                c = read();
            }

            int res = 0;
            do {
                if(c<'0'||c>'9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));

            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;

            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));
                return res * sgn;
        }

        public double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public String readString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            }
            while (!isSpaceChar(c));

            return res.toString();
        }

        public boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public String next() {
            return readString();
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
    public static void main(String args[]) throws Exception {
        new Thread(null, new Main(),"Main",1<<26).start();
    }
    long getDist(Point p1, Point p2) {
        return abs(p1.x - p2.x) + abs(p1.y - p2.y);
    }
    public void run() {
        InputReader sc = new InputReader(System.in);
        PrintWriter w = new PrintWriter(System.out);

        int n = sc.nextInt();

        TreeMap<Long, ArrayList<Point>> map = new TreeMap<>();

        Point p[] = new Point[n];
        for(int i = 0; i < n; ++i) {
            p[i] = new Point(sc.nextLong(), sc.nextLong());
            long level = max(p[i].x, p[i].y);
            if(map.get(level) == null)
                map.put(level, new ArrayList<>());
            map.get(level).add(p[i]);
        }

        for(long i : map.keySet()) {
            ArrayList<Point> list = map.get(i);

            Collections.sort(list, new Comparator<Point>() {
                public int compare(Point p1, Point p2) {
                    if(p1.y < p2.y)
                        return -1;
                    if(p1.y > p2.y)
                        return 1;
                    if(p1.x > p2.x)
                        return -1;
                    if(p1.x < p2.x)
                        return 1;
                    return 0;
                }
            });
        }

        long prevDp[], dp[];

        ArrayList<Point> prevList = new ArrayList<>();
        prevList.add(new Point(0, 0));

        prevDp = new long[1];
        prevDp[0] = 0;

        for(long i : map.keySet()) {
            ArrayList<Point> list = map.get(i);

            Point firstP = list.get(0);
            Point lastP = list.get(list.size() - 1);

            long firstVal = Long.MAX_VALUE;
            long lastVal = Long.MAX_VALUE;

            for(int j = 0; j < prevList.size(); ++j) {
                long curFirstVal = getDist(prevList.get(j), firstP) + prevDp[j];
                long curLastVal = getDist(prevList.get(j), lastP) + prevDp[j];
                firstVal = min(firstVal, curFirstVal);
                lastVal = min(lastVal, curLastVal);
            }

            dp = new long[list.size()];
            for(int j = 0; j < list.size(); ++j) {
                long val1 = firstVal + getDist(firstP, lastP) + getDist(lastP, list.get(j));
                long val2 = lastVal + getDist(lastP, firstP) + getDist(firstP, list.get(j));

                dp[j] = min(val1, val2);
            }

            prevDp = dp;
            prevList = list;
        }

        long ans = Long.MAX_VALUE;
        for(int i = 0; i < prevDp.length; ++i)
            ans = min(ans, prevDp[i]);

        w.print(ans);

        w.close();
    }
}
class Point {
    long x, y;
    Point(long a, long b) {
        x = a;
        y = b;
    }
}

import java.util.*;

public class CF1066F {

    static class Point {
        long x;
        long y;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Map<Long, Point> left = new TreeMap<>();
        Map<Long, Point> right = new TreeMap<>();
        for(int i=0;i<n;i++) {
            long x = sc.nextInt();
            long y = sc.nextInt();
            long l = Math.max(x, y);
            if(!left.containsKey(l)) {
                left.put(l, new Point(x, y));
            } else if(left.get(l).x > x){
                left.put(l, new Point(x, y));
            } else if(left.get(l).x == x){
                left.put(l, new Point(x, Math.max(y, left.get(l).y)));
            }
            if(!right.containsKey(l)) {
                right.put(l, new Point(x, y));
            } else if(right.get(l).y > y) {
                right.put(l, new Point(x, y));
            } else if(right.get(l).y == y){
                right.put(l, new Point(Math.max(right.get(l).x, x), y));
            }
        }
        long a = 0;
        long b = 0;
        long c = 0;
        long d = 0;
        Point leftpoint = new Point(0, 0);
        Point rightpoint = new Point(0, 0);
        for(Map.Entry<Long, Point> e: left.entrySet()) {
            Point lp = left.get(e.getKey());
            Point rp = right.get(e.getKey());
//            System.out.println(lp.x + " " + lp.y + " " + rp.x + " " + rp.y);
            c = dist(lp, rp) + Math.min(b + dist(lp, leftpoint), d + dist(lp, rightpoint));
            a = dist(lp, rp) + Math.min(b + dist(rp, leftpoint), d + dist(rp, rightpoint));
//            System.out.println(a + " " + c);
            leftpoint = lp;
            rightpoint = rp;
            b = a;
            d = c;
        }
        System.out.println(Math.min(a, c));
    }

    public static long dist(Point p1, Point p2) {
        return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
    }

}

//package Contest515div3;

import java.io.PrintWriter;
import java.sql.SQLOutput;
import java.util.*;

public class mainF {
    public static Scanner enter = new Scanner(System.in);
    public static PrintWriter out = new PrintWriter(System.out);
    public static void main(String[] args) {
          int n=enter.nextInt();
          point mass[] =new point[n+1];
        for (int i = 0; i <n ; i++) {
            mass[i]=new point(enter.nextLong(),enter.nextLong());
        }
        mass[n]=new point((long)1e10,(long)1e10);
        Arrays.sort(mass,0,n);
        ArrayList<point> arrayList=new ArrayList<>(n);
        //arrayList.add(mass[0]);
        arrayList.add(new point(0,0));
        arrayList.add(new point(0,0));

        //System.out.println(Arrays.toString(mass));
        for (int i = 0; i <n ; i++) {
            if(Math.max(mass[i+1].x,mass[i+1].y)>Math.max(mass[i].x,mass[i].y)){
                if(i==0){
                    arrayList.add(mass[i]);
                }
                arrayList.add(mass[i]);
                arrayList.add(mass[i+1]);
            }
            else if(i==0){
                arrayList.add(mass[i]);
            }
        }

        arrayList.remove(arrayList.size()-1);
        //System.out.println(arrayList);
        long dp[]=new long[(int)1e6];
        int last=0;
        for (int i = 2; i <arrayList.size() ; i+=2) {
            dp[i]=Math.min(dist(arrayList.get(i+1),arrayList.get(i-1))+dp[i-1],dist(arrayList.get(i+1),arrayList.get(i-2))+dp[i-2])+dist(arrayList.get(i),arrayList.get(i+1));
            dp[i+1]=Math.min(dist(arrayList.get(i),arrayList.get(i-1))+dp[i-1],dist(arrayList.get(i),arrayList.get(i-2))+dp[i-2])+dist(arrayList.get(i),arrayList.get(i+1));
            last=i+1;
        }
        out.println(Math.min(dp[last],dp[last-1]));
        out.close();
    }

    public static long dist(point a,point b){
        return Math.abs(a.x-b.x)+Math.abs(a.y-b.y);

    }

}

class point implements Comparable<point>{
    long x,y;

    public point(long x, long y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public int compareTo(point o) {
        if(Math.max(x,y)<Math.max(o.x,o.y)) return -1;
        else if(Math.max(x,y)>Math.max(o.x,o.y)) return 1;
        else{
             if(y==o.y){
                return (x<=o.x)? -1: 1;
            }
            else if(x==o.x){
                 return (y>=o.y)? -1: 1;
             }
             else{
                 return (x<=o.x)? -1: 1;
             }
        }
    }

    @Override
    public String toString() {
        return "("+x+", "+y+")";
    }
}

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import static java.lang.Math.*;

/* spar5h */

public class cf6{

	static void recur(int i, int d, int m) {

		if(i == m) {
			 dp[i][d] = 0; return;
		}

		dp[i][d] = Long.MAX_VALUE;

		long x = adj[i].get((adj[i].size() - 1) * d).x, y = adj[i].get((adj[i].size() - 1) * d).y;

		long x1 = adj[i + 1].get(0).x, y1 = adj[i + 1].get(0).y;
		long x2 = adj[i + 1].get(adj[i + 1].size() - 1).x, y2 = adj[i + 1].get(adj[i + 1].size() - 1).y;

		long dist = abs(x1 - x2) + abs(y1 - y2);

		if(dp[i + 1][0] == -1)
			recur(i + 1, 0, m);

		dp[i][d] = min(abs(x - x2) + abs(y - y2) + dist + dp[i + 1][0], dp[i][d]);

		if(dp[i + 1][1] == -1)
			recur(i + 1, 1, m);

		dp[i][d] = min(abs(x - x1) + abs(y - y1) + dist + dp[i + 1][1], dp[i][d]);

		//System.out.println(x + " " + y + " " + i + " " + d + " " + dp[i][d]);
	}

	static class pair {

		int x, y;

		pair(int x, int y) {
			this.x = x; this.y = y;
		}
	}

	static class comp implements Comparator<pair> {

		public int compare(pair a, pair b) {

			if(a.x < b.x)
				return -1;

			if(a.x > b.x)
				return 1;

			if(a.y > b.y)
				return -1;

			if(a.y < b.y)
				return 1;

			return 0;

		}
	}

	static int[] val;
	static ArrayList<pair>[] adj;
	static long[][] dp;

	public static void main(String[] args) {

		InputReader s = new InputReader(System.in);
		PrintWriter w = new PrintWriter(System.out);

		int n = s.nextInt();

		int[] x = new int[n];
		int[] y = new int[n];

		TreeSet<Integer> ts = new TreeSet<Integer>();

		for(int i = 0; i < n; i++) {

			x[i] = s.nextInt();
			y[i] = s.nextInt();

			ts.add(max(x[i], y[i]));
		}

		int m = 0;

		HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
		hm.put(0, 0);

		for(int i : ts) {
			m = m + 1; hm.put(i, m);
		}

		adj = new ArrayList[m + 1];

		for(int i = 0; i <= m; i++)
			adj[i] = new ArrayList<pair>();

		adj[0].add(new pair(0, 0));

		for(int i = 0; i < n; i++)
			adj[hm.get(max(x[i], y[i]))].add(new pair(x[i], y[i]));

		for(int i = 0; i <= m; i++)
			Collections.sort(adj[i], new comp());

		dp = new long[m + 1][2];

		for(int i = 0; i <= m; i++)
			for(int j = 0; j < 2; j++)
				dp[i][j] = -1;

		recur(0, 0, m);

		w.println(dp[0][0]);

		w.close();
	}

	static class InputReader {

		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream)
		{
			this.stream = stream;
		}

		public int read()
		{
			if (numChars==-1)
				throw new InputMismatchException();

			if (curChar >= numChars)
			{
				curChar = 0;
				try
				{
					numChars = stream.read(buf);
				}
				catch (IOException e)
				{
					throw new InputMismatchException();
				}

				if(numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public String nextLine()
		{
			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
		}
		public int nextInt()
		{
			int c = read();

			while(isSpaceChar(c))
				c = read();

			int sgn = 1;

			if (c == '-')
			{
				sgn = -1;
				c = read();
			}

			int res = 0;
			do
			{
				if(c<'0'||c>'9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));

			return res * sgn;
		}

		public long nextLong()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			long res = 0;

			do
			{
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));
				return res * sgn;
		}

		public double nextDouble()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			double res = 0;
			while (!isSpaceChar(c) && c != '.')
			{
				if (c == 'e' || c == 'E')
					return res * Math.pow(10, nextInt());
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			if (c == '.')
			{
				c = read();
				double m = 1;
				while (!isSpaceChar(c))
				{
					if (c == 'e' || c == 'E')
						return res * Math.pow(10, nextInt());
					if (c < '0' || c > '9')
						throw new InputMismatchException();
					m /= 10;
					res += (c - '0') * m;
					c = read();
				}
			}
			return res * sgn;
		}

		public String readString()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do
			{
				res.appendCodePoint(c);
				c = read();
			}
			while (!isSpaceChar(c));

			return res.toString();
		}

		public boolean isSpaceChar(int c)
		{
			if (filter != null)
				return filter.isSpaceChar(c);
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public String next()
		{
			return readString();
		}

		public interface SpaceCharFilter
		{
			public boolean isSpaceChar(int ch);
		}
	}

}

import java.io.*;
import java.util.*;

public class Main {

    public static void main(String[] args) throws Exception {

        new Main().go();
    }

    PrintWriter out;
    Reader in;
    BufferedReader br;

    Main() throws IOException {

        try {

            //br = new BufferedReader( new FileReader("input.txt") );
            //in = new Reader("input.txt");
            in = new Reader("input.txt");
            out = new PrintWriter( new BufferedWriter(new FileWriter("output.txt")) );
        }
        catch (Exception e) {

            //br = new BufferedReader( new InputStreamReader( System.in ) );
            in = new Reader();
            out = new PrintWriter( new BufferedWriter(new OutputStreamWriter(System.out)) );
        }
    }

    void go() throws Exception {

        //int t = in.nextInt();
        int cs = 1;
        int t = 1;
        while (t > 0) {
            //out.print("Case #" + cs + ": ");
            solve();
            t--;
            cs++;
        }

        out.flush();
        out.close();
    }

    int inf = 2000000000;
    int mod = 1000000007;
    double eps = 0.000000001;

    int n;
    int m;

    ArrayList<Pair>[] g;
    void solve() throws IOException {

        int n = in.nextInt();

        TreeMap<Integer, Pair> map = new TreeMap<>();

        Pair[] points = new Pair[n];
        for (int i = 0; i < n; i++) {
            int x = in.nextInt();
            int y = in.nextInt();
            int lev = Math.max(x, y);
            points[i] = new Pair(x, y);
            if (!map.containsKey(lev)) {
                map.put(lev, new Pair(i, i));
            } else {
                Pair p1 = points[map.get(lev).a];
                Pair p2 = points[map.get(lev).b];
                if (y >= p1.b && (p1.b != y || p1.a > x)) {
                    map.get(lev).a = i;
                }

                if (x >= p2.a && (p2.a != x || p2.b > y)) {
                    map.get(lev).b = i;
                }
            }
        }

        int levs = map.keySet().size();
        long[][] dp = new long[2][levs + 1];
        long ans = 0;
        int pos = 1;
        Pair prev1 = new Pair(0, 0);
        Pair prev2 = new Pair(0, 0);
        for (int k : map.keySet()) {
            Pair p1 = points[map.get(k).a];
            Pair p2 = points[map.get(k).b];
            ans += dist(p1, p2);

            dp[0][pos] = Math.min(
                    dp[0][pos - 1] + dist(p2, prev1),
                    dp[1][pos - 1] + dist(p2, prev2));

            dp[1][pos] = Math.min(
                    dp[0][pos - 1] + dist(p1, prev1),
                    dp[1][pos - 1] + dist(p1, prev2));

            prev1 = p1;
            prev2 = p2;
            pos++;
            //System.err.println(k);
            //System.err.println(p1.a + " " + p1.b);
            //System.err.println(p2.a + " " + p2.b);
        }

        ans += Math.min(dp[0][levs], dp[1][levs]);
        out.println(ans);
    }

    int dist(Pair p1, Pair p2) {
        return Math.abs(p1.a - p2.a) + Math.abs(p1.b - p2.b);
    }

    class Pair implements Comparable<Pair>{

        int a;
        int b;

        Pair(int a, int b) {

            this.a = a;
            this.b = b;
        }

        public int compareTo(Pair p) {
            if (a != p.a)
                return Integer.compare(a, p.a);
            else
                return Integer.compare(b, p.b);
        }
    }

    class Item {

        int a;
        int b;
        int c;

        Item(int a, int b, int c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }

    }

    class Reader {

        BufferedReader  br;
        StringTokenizer tok;

        Reader(String file) throws IOException {
            br = new BufferedReader( new FileReader(file) );
        }

        Reader() throws IOException {
            br = new BufferedReader( new InputStreamReader(System.in) );
        }

        String next() throws IOException {

            while (tok == null || !tok.hasMoreElements())
                tok = new StringTokenizer(br.readLine());
            return tok.nextToken();
        }

        int nextInt() throws NumberFormatException, IOException {
            return Integer.valueOf(next());
        }

        long nextLong() throws NumberFormatException, IOException {
            return Long.valueOf(next());
        }

        double nextDouble() throws NumberFormatException, IOException {
            return Double.valueOf(next());
        }

        String nextLine() throws IOException {
            return br.readLine();
        }

    }

    static class InputReader
    {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public InputReader()
        {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public InputReader(String file_name) throws IOException
        {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException
        {
            byte[] buf = new byte[64]; // line length
            int cnt = 0, c;
            while ((c = read()) != -1)
            {
                if (c == '\n')
                    break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException
        {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do
            {
                ret = ret * 10 + c - '0';
            }  while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        public long nextLong() throws IOException
        {
            long ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');
            if (neg)
                return -ret;
            return ret;
        }

        public double nextDouble() throws IOException
        {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();

            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');

            if (c == '.')
            {
                while ((c = read()) >= '0' && c <= '9')
                {
                    ret += (c - '0') / (div *= 10);
                }
            }

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException
        {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1)
                buffer[0] = -1;
        }

        private byte read() throws IOException
        {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException
        {
            if (din == null)
                return;
            din.close();
        }
    }

}

import java.io.*;
import java.math.*;
import java.util.*;
import java.awt.Point;

public class Main {
	static final long MOD = 998244353L;
	//static final long INF = -1000000000000000007L;
	//static final long MOD = 1000000007L;
	//static final int INF = 1000000007;

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		PrintWriter pw = new PrintWriter(System.out);
		int N = sc.ni();
		int[][] points = new int[N+1][2];
		for (int i = 1; i <= N; i++) {
			points[i] = new int[]{sc.ni(),sc.ni()};
		}
		points = sortPoints(points);

		int[] rungs = new int[N+1];
		for (int i = 0; i <= N; i++) {
			rungs[i] = Math.max(points[i][0],points[i][1]);
		}
		long[][] dp = new long[N+5][2];
		//dp[i][0] represents leaving the rung at the left most point
		//dp[i][1] represents leaving the run at the right most point
		int[] left = {0,0};
		int[] right = {0,0};
		int i = 0;
		int index = 1;
		while (i <= N) {
			int j = i;
			int[] newLeft = points[i];
			while (j <= N && rungs[j] == rungs[i]) {
				j++;
			}
			int[] newRight = points[j-1];

			long distLR = dist(newLeft,newRight);

			dp[index][0] = distLR+Math.min(dp[index-1][0]+dist(left,newRight),dp[index-1][1]+dist(right,newRight));
			dp[index][1] = distLR+Math.min(dp[index-1][0]+dist(left,newLeft),dp[index-1][1]+dist(right,newLeft));
			left = newLeft;
			right = newRight;
			index++;
			i = j;
		}

		pw.println(Math.min(dp[index-1][0],dp[index-1][1]));
		pw.close();
 	}

	public static long dist(int[] p, int[] q) {
		return (long)(Math.abs(p[0]-q[0])+Math.abs(p[1]-q[1]));
	}

    public static int[][] sortPoints(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  if (Math.max(arr1[0],arr1[1]) != Math.max(arr2[0],arr2[1])) {
					  return Math.max(arr1[0],arr1[1]) - Math.max(arr2[0],arr2[1]);
				  } else {
					  int[] leftMost = {0,Math.max(arr1[0],arr1[1])};
					  long d = dist(leftMost,arr1)-dist(leftMost,arr2);
					  if (d < 0) {
						  return -1;
					  } else {
						  return 1;
					  }
				  }
	          }
		});
		return array;
	}

    public static int[][] sort(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  return arr1[0]-arr2[0]; //ascending order
	          }
		});
		return array;
	}

    public static long[][] sort(long[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    long[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<long[]>() {
			  @Override
			  //Descending order
        	  public int compare(long[] arr1, long[] arr2) {
				  if (arr2[0] < arr1[0])
					  return -1;
				  if (arr2[0] > arr1[0])
					  return 1;
				  return 0;
	          }
		});
		return array;
	}

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int ni() {
            return Integer.parseInt(next());
        }

        long nl() {
            return Long.parseLong(next());
        }

        double nd() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.FilterInputStream;
import java.io.BufferedInputStream;
import java.io.InputStream;

/**
 * @author khokharnikunj8
 */

public class Main {
    public static void main(String[] args) {
        new Thread(null, new Runnable() {
            public void run() {
                new Main().solve();
            }
        }, "1", 1 << 26).start();
    }

    void solve() {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        ScanReader in = new ScanReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        FYetAnother2DWalking solver = new FYetAnother2DWalking();
        solver.solve(1, in, out);
        out.close();
    }

    static class FYetAnother2DWalking {
        pair[][] levels;

        long findIt(int x, int y, int x1, int y1) {
            return Math.abs(x - x1) + Math.abs(y - y1);
        }

        public void solve(int testNumber, ScanReader in, PrintWriter out) {
            int n = in.scanInt() + 1;
            levels = new pair[n][2];
            for (int i = 0; i < n; i++) levels[i][0] = new pair(-1, -1);
            pair[] ar = new pair[n];
            for (int i = 0; i < n - 1; i++) ar[i] = new pair(in.scanInt(), in.scanInt());
            ar[n - 1] = new pair(0, 0);
            Arrays.sort(ar, (o1, o2) -> (Math.max(o1.x, o1.y) - Math.max(o2.x, o2.y)));
            int total_lev = -1;
            int prev = -1;
            for (int i = 0; i < n; i++) {
                if (Math.max(ar[i].x, ar[i].y) != prev) total_lev++;
                if (levels[total_lev][0].x == -1) {
                    levels[total_lev][0] = levels[total_lev][1] = ar[i];
                } else {
                    if (ar[i].x == Math.max(ar[i].x, ar[i].y)) {
                        if (ar[i].y > levels[total_lev][0].y) levels[total_lev][0] = ar[i];
                        if (ar[i].y < levels[total_lev][1].y) levels[total_lev][1] = ar[i];
                    } else {
                        if (ar[i].x < levels[total_lev][0].x) levels[total_lev][0] = ar[i];
                        if (ar[i].x > levels[total_lev][1].x) levels[total_lev][1] = ar[i];
                    }
                }
                prev = Math.max(ar[i].x, ar[i].y);
            }
            total_lev++;
            long[][] dp = new long[total_lev][2];
            for (int i = 0; i < total_lev; i++) Arrays.fill(dp[i], 2 * 1000000000000000000l);
            dp[0][0] = dp[0][1] = findIt(levels[0][1].x, levels[0][1].y, levels[0][0].x, levels[0][0].y);
            for (int i = 1; i < total_lev; i++) {
                dp[i][0] = Math.min(dp[i][0], dp[i - 1][0] + findIt(levels[i][1].x, levels[i][1].y, levels[i - 1][0].x, levels[i - 1][0].y) + findIt(levels[i][1].x, levels[i][1].y, levels[i][0].x, levels[i][0].y));
                dp[i][1] = Math.min(dp[i][1], dp[i - 1][1] + findIt(levels[i][0].x, levels[i][0].y, levels[i - 1][1].x, levels[i - 1][1].y) + findIt(levels[i][1].x, levels[i][1].y, levels[i][0].x, levels[i][0].y));
                dp[i][0] = Math.min(dp[i][0], dp[i - 1][1] + findIt(levels[i][1].x, levels[i][1].y, levels[i - 1][1].x, levels[i - 1][1].y) + findIt(levels[i][1].x, levels[i][1].y, levels[i][0].x, levels[i][0].y));
                dp[i][1] = Math.min(dp[i][1], dp[i - 1][0] + findIt(levels[i][0].x, levels[i][0].y, levels[i - 1][0].x, levels[i - 1][0].y) + findIt(levels[i][1].x, levels[i][1].y, levels[i][0].x, levels[i][0].y));
            }
            out.println(Math.min(dp[total_lev - 1][0], dp[total_lev - 1][1]));
        }

        class pair {
            int x;
            int y;

            public pair(int x, int y) {
                this.x = x;
                this.y = y;
            }

        }

    }

    static class ScanReader {
        private byte[] buf = new byte[4 * 1024];
        private int index;
        private BufferedInputStream in;
        private int total;

        public ScanReader(InputStream inputStream) {
            in = new BufferedInputStream(inputStream);
        }

        private int scan() {
            if (index >= total) {
                index = 0;
                try {
                    total = in.read(buf);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (total <= 0) return -1;
            }
            return buf[index++];
        }

        public int scanInt() {
            int integer = 0;
            int n = scan();
            while (isWhiteSpace(n)) n = scan();
            int neg = 1;
            if (n == '-') {
                neg = -1;
                n = scan();
            }
            while (!isWhiteSpace(n)) {
                if (n >= '0' && n <= '9') {
                    integer *= 10;
                    integer += n - '0';
                    n = scan();
                }
            }
            return neg * integer;
        }

        private boolean isWhiteSpace(int n) {
            if (n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true;
            else return false;
        }

    }
}

/*
Keep solving problems.
*/

import java.util.*;
import java.io.*;

public class CFA {
    BufferedReader br;
    PrintWriter out;
    StringTokenizer st;
    boolean eof;
    private static final long MOD = 1000L * 1000L * 1000L + 7;
    private static final int[] dx = {0, -1, 0, 1};
    private static final int[] dy = {1, 0, -1, 0};
    private static final String yes = "Yes";
    private static final String no = "No";

    class Point implements Comparable<Point> {
        long x;
        long y;
        long max;
        public Point(long x, long y) {
            this.x = x;
            this.y = y;
            max = Math.max(x, y);
        }

        @Override
        public int compareTo(Point o) {
            return Long.compare(max, o.max);
        }

        @Override
        public String toString() {
            return x + " " + y;
        }
    }

    int n;
    Point[] arr;
    List<List<Point>> layers = new ArrayList<>();
    void solve() throws IOException {
        n = nextInt();
        arr = new Point[n];
        for (int i = 0; i < n; i++) {
            long x = nextLong();
            long y = nextLong();
            arr[i] = new Point(x, y);
        }

        Arrays.sort(arr);
        List<Point> first = new ArrayList<>();
        first.add(new Point(0, 0));
        layers.add(first);
        int start = 0;
        while (start < n) {
            int end = start;
            List<Point> ls = new ArrayList<>();
            while (end < n && arr[end].max == arr[start].max) {
                ls.add(arr[end]);
                end++;
            }

            layers.add(ls);
            start = end;
        }

        for (List<Point> layer : layers) {
            Collections.sort(layer, new Comparator<Point>() {
                @Override
                public int compare(Point o1, Point o2) {
                    if (o1.x != o2.x) {
                        return Long.compare(o1.x, o2.x);
                    }

                    return Long.compare(o2.y, o1.y);
                }
            });
        }

        int sz = layers.size();
        long[][] dp = new long[sz][2];
        dp[0][0] = 0;
        dp[0][1] = 0;
        for (int i = 1; i < sz; i++) {
            Arrays.fill(dp[i], Long.MAX_VALUE);
        }

        for (int i = 0; i < sz - 1; i++) {
            //start from dp[i][0]
            Point c0 = layers.get(i).get(0);
            int m = layers.get(i).size();
            Point c1 = layers.get(i).get(m - 1);

            Point n0 = layers.get(i + 1).get(0);
            m = layers.get(i + 1).size();
            Point n1 = layers.get(i + 1).get(m - 1);

            dp[i + 1][1] = Math.min(dp[i + 1][1], dp[i][0] + dist(c0, n0) + dist(n0, n1));
            dp[i + 1][0] = Math.min(dp[i + 1][0], dp[i][0] + dist(c0, n1) + dist(n1, n0));

            dp[i + 1][1] = Math.min(dp[i + 1][1], dp[i][1] + dist(c1, n0) + dist(n0, n1));
            dp[i + 1][0] = Math.min(dp[i + 1][0], dp[i][1] + dist(c1, n1) + dist(n1, n0));
        }

        outln(Math.min(dp[sz - 1][0], dp[sz - 1][1]));
    }

    long dist(Point p1, Point p2) {
        return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
    }

    void shuffle(int[] a) {
        int n = a.length;
        for(int i = 0; i < n; i++) {
            int r = i + (int) (Math.random() * (n - i));
            int tmp = a[i];
            a[i] = a[r];
            a[r] = tmp;
        }
    }
    long gcd(long a, long b) {
        while(a != 0 && b != 0) {
            long c = b;
            b = a % b;
            a = c;
        }
        return a + b;
    }
    private void outln(Object o) {
        out.println(o);
    }
    private void out(Object o) {
        out.print(o);
    }
    private void formatPrint(double val) {
        outln(String.format("%.9f%n", val));
    }
    public CFA() throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }
    public static void main(String[] args) throws IOException {
        new CFA();
    }

    public long[] nextLongArr(int n) throws IOException{
        long[] res = new long[n];
        for(int i = 0; i < n; i++)
            res[i] = nextLong();
        return res;
    }
    public int[] nextIntArr(int n) throws IOException {
        int[] res = new int[n];
        for(int i = 0; i < n; i++)
            res[i] = nextInt();
        return res;
    }
    public String nextToken() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception e) {
                eof = true;
                return null;
            }
        }
        return st.nextToken();
    }
    public String nextString() {
        try {
            return br.readLine();
        } catch (IOException e) {
            eof = true;
            return null;
        }
    }
    public int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }
    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
}

import java.io.*;
import java.util.*;

public class YetAnother2DWalking {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver solver = new Solver();
        solver.solve(inp, out);
        out.close();
    }

    static class Solver {
        private void solve(InputReader inp, PrintWriter out) {
            int n = inp.nextInt();
            HashMap<Integer, Coord> left = new HashMap<>();
            HashMap<Integer, Coord> right = new HashMap<>();
            Set<Integer> temp = new HashSet<>();
            for (int i = 0; i < n; i++) {
                int x = inp.nextInt();
                int y = inp.nextInt();
                int layer = Math.max(x, y);
                temp.add(layer);
                Coord l = left.getOrDefault(layer, null);
                Coord r = right.getOrDefault(layer, null);
                if (l == null || x < l.x || y > l.y) left.put(layer, new Coord(x, y));
                if (r == null || x > r.x || y < r.y) right.put(layer, new Coord(x, y));
            }
            ArrayList<Integer> layers = new ArrayList<>(temp);
            Collections.sort(layers);
            Coord l = new Coord(0, 0);
            Coord r = new Coord(0, 0);
            long resL = 0, resR = 0;
            for (Integer layer: layers) {
                //out.println("\n" + layer);
                Coord newL = left.get(layer);
                //out.println(newL.x + " " + newL.y);
                Coord newR = right.get(layer);
                //out.println(newR.x + " " + newR.y);
                long leftToRight = Math.abs(newL.x - newR.x) + Math.abs(newL.y - newR.y);

                long a = resL + Math.abs(l.x - newR.x) + Math.abs(l.y - newR.y) + leftToRight;
                long b = resR + Math.abs(r.x - newR.x) + Math.abs(r.y - newR.y) + leftToRight;

                long c = resR + Math.abs(r.x - newL.x) + Math.abs(r.y - newL.y) + leftToRight;
                long d = resL + Math.abs(l.x - newL.x) + Math.abs(l.y - newL.y) + leftToRight;

                resL = Math.min(a, b);
                resR = Math.min(c, d);

                l = left.get(layer);
                r = right.get(layer);
            }
            out.println(Math.min(resL, resR));
        }

        static class Coord {
            long x;
            long y;
            public Coord(int x, int y) {
                this.x = x;
                this.y = y;
            }
        }
    }

    static class InputReader {
        BufferedReader reader;
        StringTokenizer tokenizer;

        InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
    }
}

import java.io.*;
import java.util.*;
import java.lang.*;
public class F {

    public static void main(String[] args)throws Throwable {

        FastScanner sc = new FastScanner();

        int n = sc.nextInt() + 1;

        Point[] points = new Point[n];

        // add 0,0 point
        points[0] = new Point(0, 0);
        // read given points
        for (int i=1; i<n; i++) {
            points[i] = new Point(sc.nextLong(), sc.nextLong());
        }

        Arrays.sort(points);

        Point a = new Point(-1, -1);
        Point b = new Point(-1, -1);
        Point oldA = new Point(-1, -1);
        Point oldB = new Point(-1, -1);

        long distA = 0, distB = 0;
        long tmpDist, tmpA1, tmpA2, tmpB1 , tmpB2;

        int i = n-1;

        boolean initialLoop = true;

        while (i>-1) {

            oldA = a;
            oldB = b;

            // determine new points a, b
            a = points[i];
            while(true) {
                if (i < 1 || points[i-1].level < a.level) {
                    b = points[i];
                    break;
                }
                i--;
            }
            i--;

            // System.out.println("---");

            // System.out.println("a: " + a.x + " " + a.y);
            // System.out.println("b: " + b.x + " " + b.y);
            // System.out.println("oldA: " + oldA.x + " " + oldA.y);
            // System.out.println("oldB: " + oldB.x + " " + oldB.y);

            tmpDist = a.distTo(b);

            distA += tmpDist;
            distB += tmpDist;

            // A and B must switch each time
            tmpDist = distA;
            distA = distB;
            distB = tmpDist;

            if (initialLoop) {
                initialLoop = false;
                continue;
            }

            tmpA1 = a.distTo(oldA) + distA;
            tmpA2 = a.distTo(oldB) + distB;
            tmpB1 = b.distTo(oldA) + distA;
            tmpB2 = b.distTo(oldB) + distB;

            // System.out.println("distA " + distA);
            // System.out.println("distB " + distB);

            // System.out.println("choices for distA " + tmpA1 + " (+"  + a.distTo(oldA) + ") and " + tmpA2 + " (+"  + a.distTo(oldB) + ")");
            // System.out.println("choices for distB " + tmpB1 + " (+"  + b.distTo(oldA) + ") and " + tmpB2 + " (+"  + b.distTo(oldB) + ")");

            distA = Math.min(tmpA1, tmpA2); // take old path A leading to A, or take old path B leading to A
            distB = Math.min(tmpB1, tmpB2);

            // System.out.println("distA " + distA);
            // System.out.println("distB " + distB);

            // System.out.println("---");

            if (i < 0) {
                break;
            }
        }

        System.out.println(Math.min(distA, distB));
    }

    static class Point implements Comparable<Point> {

        public long x, y;
        public long level;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
            this.level = x>y ? x : y;
        }

        @Override
        public int compareTo(Point point) {
            if (this.level < point.level) {
                return -1;
            } else if (this.level > point.level) {
                return 1;
            } else {
                if (this.y > point.y) {
                    return -1;
                } else if (this.y < point.y) {
                    return 1;
                } else {
                    if (this.x < point.x) {
                        return -1;
                    } else if (this.x > point.x) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        }

        public long distTo(Point point) {
            return(Math.abs(point.x - this.x) + Math.abs(point.y - this.y));
        }
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                    }
                catch (IOException e) {
                    e.printStackTrace();
                    }
                }
            return st.nextToken();
            }

        int nextInt() {
            return Integer.parseInt(next());
            }

        long nextLong() {
            return Long.parseLong(next());
            }

        double nextDouble() {
            return Double.parseDouble(next());
            }

        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;
import java.util.List;

public class Main {

	InputStream is;
	PrintWriter out;
	String INPUT = "";

	private static final long MOD = 998244353L;

	List<Integer> g[];

	void solve() {
		StringBuffer sb = new StringBuffer();
		int N = ni();
		int[][] a = new int[N + 1][2];
		for (int i = 1; i <= N; i++) {
			a[i][0] = ni();
			a[i][1] = ni();
		}

		Arrays.sort(a, new Comparator<int[]>() {
			public int compare(int[] o1, int[] o2) {
				int ret = Math.max(o1[0], o1[1]) - Math.max(o2[0], o2[1]);
				if (ret == 0)
					ret = o1[0] - o2[0];
				if (ret == 0)
					ret = o2[1] - o1[1];
				return ret;
			}
		});
		List<int[]> ends = new ArrayList<int[]>();
		for (int i = 0; i <= N;) {
			int level = Math.max(a[i][0], a[i][1]);
			int j = i + 1;
			for (; j <= N && level == Math.max(a[j][0], a[j][1]); j++)
				;
			ends.add(new int[] { i, j - 1 });
			i = j;
		}

		long dp[] = new long[2];
		for (int i = 1; i < ends.size(); i++) {
			int s0 = ends.get(i - 1)[0];
			int e0 = ends.get(i - 1)[1];
			int s = ends.get(i)[0];
			int e = ends.get(i)[1];
			int curDist = dist(a[s], a[e]); // s->e == e->s
			long cur[] = new long[] {
					// s->e + (1: s0->e0->s, 2: e0->s0->s)
					curDist + Math.min(dp[0] + dist(a[e0], a[s]), dp[1] + dist(a[s0], a[s])),
					// e->s + (1: s0->e0->e, 2: e0->s0->e)
					curDist + Math.min(dp[0] + dist(a[e0], a[e]), dp[1] + dist(a[s0], a[e])) };
			dp = cur;
		}

		out.println(Math.min(dp[0], dp[1]));

	}

	private int dist(int[] p1, int[] p2) {
		return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]);
	}

	private List<Integer>[] getG(int N, int M) {
		List<Integer>[] ret = new List[N];
		for (int i = 0; i < N; i++)
			ret[i] = new ArrayList<Integer>();
		for (int i = 0; i < M; i++) {
			int u = ni() - 1;
			int v = ni() - 1;
			ret[u].add(v);
		}
		return ret;
	}

	private long gcd(long a, long b) {
		while (a != 0) {
			long tmp = b % a;
			b = a;
			a = tmp;
		}
		return b;
	}

	void run() throws Exception {
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		if (!INPUT.isEmpty())
			tr(System.currentTimeMillis() - s + "ms");
	}

	public static void main(String[] args) throws Exception {
		new Main().run();
	}

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;
	private boolean vis[];

	private int readByte() {
		if (lenbuf == -1)
			throw new InputMismatchException();
		if (ptrbuf >= lenbuf) {
			ptrbuf = 0;
			try {
				lenbuf = is.read(inbuf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (lenbuf <= 0)
				return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) {
		return !(c >= 33 && c <= 126);
	}

	private int skip() {
		int b;
		while ((b = readByte()) != -1 && isSpaceChar(b))
			;
		return b;
	}

	private double nd() {
		return Double.parseDouble(ns());
	}

	private char nc() {
		return (char) skip();
	}

	private String ns() {
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != '
									// ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n) {
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while (p < n) {
			if (!(isSpaceChar(b)))
				buf[p++] = (char) b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m) {
		char[][] map = new char[n][];
		for (int i = 0; i < n; i++)
			map[i] = ns(m);
		return map;
	}

	private int[] na(int n) {
		int[] a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = ni();
		return a;
	}

	private Integer[] na2(int n) {
		Integer[] a = new Integer[n];
		for (int i = 0; i < n; i++)
			a[i] = ni();
		return a;
	}

	private int[][] na(int n, int m) {
		int[][] a = new int[n][];
		for (int i = 0; i < n; i++)
			a[i] = na(m);
		return a;
	}

	private Integer[][] na2(int n, int m) {
		Integer[][] a = new Integer[n][];
		for (int i = 0; i < n; i++)
			a[i] = na2(m);
		return a;
	}

	private int ni() {
		int num = 0, b;
		boolean minus = false;
		while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
			;
		if (b == '-') {
			minus = true;
			b = readByte();
		}

		while (true) {
			if (b >= '0' && b <= '9') {
				num = num * 10 + (b - '0');
			} else {
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl() {
		long num = 0;
		int b;
		boolean minus = false;
		while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
			;
		if (b == '-') {
			minus = true;
			b = readByte();
		}

		while (true) {
			if (b >= '0' && b <= '9') {
				num = num * 10 + (b - '0');
			} else {
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private static void tr(Object... o) {
		System.out.println(Arrays.deepToString(o));
	}
}

import java.util.*;
import java.io.*;

public class Main {
	public static void main(String args[]) {new Main().run();}

	Scanner in = new Scanner(System.in);
	PrintWriter out = new PrintWriter(System.out);
	void run(){
	    out.println(work());
	    out.flush();
	}
	long work() {
	    int n=in.nextInt();
	    TreeMap<Integer,ArrayList<int[]>> map=new TreeMap<>();
	    for(int i=0;i<n;i++){
	        int a=in.nextInt();
	        int b=in.nextInt();
	        int c=Math.max(a,b);
	        if(map.get(c)==null){
	            map.put(c,new ArrayList<int[]>());
	        }
	        map.get(c).add(new int[]{a,b});
	    }
	    for(int key:map.keySet()){
	        ArrayList<int[]> l=map.get(key);
	        Collections.sort(l,new Comparator<int[]>(){
	            public int compare(int[] p1,int[] p2){
	                if(p1[0]==p2[0]){
	                    return p2[1]-p1[1];
	                }
	                return p1[0]-p2[0];
	            }
	        });
	    }

	    ArrayList<ArrayList<int[]>> list=new ArrayList<>();
	    ArrayList<int[]> ll=new ArrayList<>();
	    ll.add(new int[]{0,0});
	    list.add(ll);
	    for(int key:map.keySet()){
	       //if(key==4){
	       //    out.println(map.get(key).size());

	       //}
	        list.add(map.get(key));
	    }

	    long[][] dp=new long[list.size()][2];
	    for(int i=list.size()-1;i>=0;i--){
	        ArrayList<int[]> l=list.get(i);
	        int[] s=l.get(0);
	        int[] e=l.get(l.size()-1);
	        long len=Math.abs(s[0]-e[0])+Math.abs(s[1]-e[1]);
	        if(i==list.size()-1){
	            dp[i][0]=len;
	            dp[i][1]=len;
	        }else{
	            ArrayList<int[]> l2=list.get(i+1);
	            int[] ps=l2.get(0);
	            int[] pe=l2.get(l2.size()-1);

	            dp[i][0]=len+dp[i+1][0]+Math.abs(e[0]-ps[0])+Math.abs(e[1]-ps[1]);
	            dp[i][0]=Math.min(dp[i][0],len+dp[i+1][1]+Math.abs(e[0]-pe[0])+Math.abs(e[1]-pe[1]));

	            dp[i][1]=len+dp[i+1][0]+Math.abs(s[0]-ps[0])+Math.abs(s[1]-ps[1]);
	            dp[i][1]=Math.min(dp[i][1],len+dp[i+1][1]+Math.abs(s[0]-pe[0])+Math.abs(s[1]-pe[1]));
	        }

	       // out.println(Math.max(s[0],s[1])+",,"+"dp0="+dp[i][0]+",dp1="+dp[i][1]);
	    }
	    return dp[0][0];
	}
}

import java.util.*;
import java.io.*;
public class Main {
    static class Scan {
        private byte[] buf=new byte[1024];
        private int index;
        private InputStream in;
        private int total;
        public Scan()
        {
            in=System.in;
        }
        public int scan()throws IOException
        {
            if(total<0)
            throw new InputMismatchException();
            if(index>=total)
            {
                index=0;
                total=in.read(buf);
                if(total<=0)
                return -1;
            }
            return buf[index++];
        }
        public int scanInt()throws IOException
        {
            int integer=0;
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            int neg=1;
            if(n=='-')
            {
                neg=-1;
                n=scan();
            }
            while(!isWhiteSpace(n))
            {
                if(n>='0'&&n<='9')
                {
                    integer*=10;
                    integer+=n-'0';
                    n=scan();
                }
                else throw new InputMismatchException();
            }
            return neg*integer;
        }
        public double scanDouble()throws IOException
        {
            double doub=0;
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            int neg=1;
            if(n=='-')
            {
                neg=-1;
                n=scan();
            }
            while(!isWhiteSpace(n)&&n!='.')
            {
                if(n>='0'&&n<='9')
                {
                    doub*=10;
                    doub+=n-'0';
                    n=scan();
                }
                else throw new InputMismatchException();
            }
            if(n=='.')
            {
                n=scan();
                double temp=1;
                while(!isWhiteSpace(n))
                {
                    if(n>='0'&&n<='9')
                    {
                        temp/=10;
                        doub+=(n-'0')*temp;
                        n=scan();
                    }
                    else throw new InputMismatchException();
                }
            }
            return doub*neg;
        }
        public String scanString()throws IOException
        {
            StringBuilder sb=new StringBuilder();
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            while(!isWhiteSpace(n))
            {
                sb.append((char)n);
                n=scan();
            }
            return sb.toString();
        }
        private boolean isWhiteSpace(int n)
        {
            if(n==' '||n=='\n'||n=='\r'||n=='\t'||n==-1)
            return true;
            return false;
        }
    }

    public static void sort(int arr[],int l,int r) {    //sort(arr,0,n-1);
        if(l==r) {
            return;
        }
        int mid=(l+r)/2;
        sort(arr,l,mid);
        sort(arr,mid+1,r);
        merge(arr,l,mid,mid+1,r);
    }
    public static void merge(int arr[],int l1,int r1,int l2,int r2) {
        int tmp[]=new int[r2-l1+1];
        int indx1=l1,indx2=l2;
        //sorting the two halves using a tmp array
        for(int i=0;i<tmp.length;i++) {
            if(indx1>r1) {
                tmp[i]=arr[indx2];
                indx2++;
                continue;
            }
            if(indx2>r2) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            if(arr[indx1]<arr[indx2]) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            tmp[i]=arr[indx2];
            indx2++;
        }
        //Copying the elements of tmp into the main array
        for(int i=0,j=l1;i<tmp.length;i++,j++) {
            arr[j]=tmp[i];
        }
    }

    public static void sort(long arr[],int l,int r) {    //sort(arr,0,n-1);
        if(l==r) {
            return;
        }
        int mid=(l+r)/2;
        sort(arr,l,mid);
        sort(arr,mid+1,r);
        merge(arr,l,mid,mid+1,r);
    }
    public static void merge(long arr[],int l1,int r1,int l2,int r2) {
        long tmp[]=new long[r2-l1+1];
        int indx1=l1,indx2=l2;
        //sorting the two halves using a tmp array
        for(int i=0;i<tmp.length;i++) {
            if(indx1>r1) {
                tmp[i]=arr[indx2];
                indx2++;
                continue;
            }
            if(indx2>r2) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            if(arr[indx1]<arr[indx2]) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            tmp[i]=arr[indx2];
            indx2++;
        }
        //Copying the elements of tmp into the main array
        for(int i=0,j=l1;i<tmp.length;i++,j++) {
            arr[j]=tmp[i];
        }
    }
    static int n,x[],y[],lft[],rgt[];
    static long dp[][];
    public static void main(String args[]) throws IOException {
        Scan input=new Scan();
        n=input.scanInt()+1;
        int max=0;
        x=new int[n];
        y=new int[n];
        ArrayList<Integer> arrli=new ArrayList<>();
        Set<Integer> hashset=new HashSet<>();
        hashset.add(0);
        arrli.add(0);
        for(int i=1;i<n;i++) {
            x[i]=input.scanInt();
            y[i]=input.scanInt();
            if(!hashset.contains(Math.max(x[i],y[i]))) {
                hashset.add(Math.max(x[i],y[i]));
                arrli.add(Math.max(x[i],y[i]));
            }
        }
        arrli.sort(null);
        max=arrli.size();
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<arrli.size();i++) {
//            System.out.print(arrli.get(i)+" ");
            map.put(arrli.get(i), i);
        }
//        System.out.println();
        lft=new int[max];
        rgt=new int[max];
        Arrays.fill(lft, -1);
        Arrays.fill(rgt, -1);
        for(int i=0;i<n;i++) {
//            System.out.println(Math.max(x[i], y[i]));
            int indx=map.get(Math.max(x[i], y[i]));
            if(lft[indx]==-1) {
                lft[indx]=rgt[indx]=i;
                continue;
            }
            if(x[i]<x[lft[indx]]) {
                lft[indx]=i;
            }
            else if(x[i]==x[lft[indx]] && y[i]>y[lft[indx]]) {
                lft[indx]=i;
            }
            if(y[i]<y[rgt[indx]]) {
                rgt[indx]=i;
            }
            else if(y[i]==y[rgt[indx]] && x[i]>x[rgt[indx]]) {
                rgt[indx]=i;
            }
        }
        dp=new long[lft.length][2];
        for(int i=0;i<dp.length;i++) {
            for(int j=0;j<dp[0].length;j++) {
                dp[i][j]=-1;
            }
        }
        System.out.println(solve(0,false));
    }
    public static long solve(int indx,boolean curr) {
        if(indx==lft.length-1) {
            return dist(lft[indx],rgt[indx]);
        }
        if(dp[indx][curr?0:1]!=-1) {
            return dp[indx][curr?0:1];
        }
        int tmpx=x[curr?lft[indx]:rgt[indx]];
        int tmpy=y[curr?lft[indx]:rgt[indx]];
        long min=Long.MAX_VALUE;
        min=Math.min(min,dist(curr?lft[indx]:rgt[indx],lft[indx+1])+dist(lft[indx],rgt[indx])+solve(indx+1,false));
        min=Math.min(min,dist(curr?lft[indx]:rgt[indx],rgt[indx+1])+dist(lft[indx],rgt[indx])+solve(indx+1,true));
        dp[indx][curr?0:1]=min;
        return min;
    }
    public static long dist(int indx1,int indx2) {
        return Math.abs(x[indx1]-x[indx2])+Math.abs(y[indx1]-y[indx2]);
    }
}

import java.util.*;

public class ContestE {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Map<Integer, Integer[][]> map = new HashMap<>();
    	map.put(0, new Integer[][] {
    		{0,0},// top left
    		{0,0}// bottom right
    	});
        for(int i=0;i<n;i++){
        	int x = in.nextInt();
        	int y = in.nextInt();
        	int l = level(x,y);
        	if(map.containsKey(l)) {
        		Integer arr[][] = map.get(l);
        		if(x==l && y<arr[1][1]) {
        			arr[1][0] = x;
        			arr[1][1] = y;
        		}
        		if(y==l && x<arr[0][0]) {
        			arr[0][0] = x;
        			arr[0][1] = y;
        		}
        	}else {
            	map.put(l, new Integer[][] {
            		{x,y},// top left
            		{x,y}// bottom right
            	});
        	}
        }
        int prevLevel = -1;
        long distancetop = 0;
        long distancebottom = 0;
        for(Map.Entry<Integer, Integer[][]> e :map.entrySet()) {
        	Integer arr[][] = e.getValue();
        	if(prevLevel>=0) {
	        	Integer arrPrev[][] = map.get(prevLevel);
	        	long tmpdistancetop;
	        	long tmpdistancebottom;
	        	if(distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]) >
	        		distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1])) {
		        	tmpdistancetop = distancebottom + distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1]);
	        	}else {
		        	tmpdistancetop = distancetop + distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]);
	        	}
	        	if(distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]) >
	        		distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1])) {
		        	tmpdistancebottom = distancebottom + distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1]);
	        	}else {
		        	tmpdistancebottom = distancetop + distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]);
	        	}
	        	distancetop = tmpdistancebottom + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
	        	distancebottom = tmpdistancetop + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
        	}
        	prevLevel = e.getKey();
        }
        System.out.println(distancetop<distancebottom?distancetop:distancebottom);
        in.close();
	}

	public static void print(Integer[][] arr) {
		for(int i=0;i<arr.length;i++) {
			for(int j=0;j<arr[i].length;j++) {
				System.out.print(arr[i][j]+" ");
			}
			System.out.println();
		}
	}

	public static int level(int x, int y) {
		return Math.max(x, y);
	}

	public static long distance(int x1, int y1, int x2, int y2) {
		return ((long)Math.abs(x1-x2))+Math.abs(y1-y2);
	}
}

import java.util.*;

public class ContestE {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Map<Integer, Integer[][]> map = new HashMap<>();
    	map.put(0, new Integer[][] {
    		{0,0},// top left
    		{0,0}// bottom right
    	});
        for(int i=0;i<n;i++){
        	int x = in.nextInt();
        	int y = in.nextInt();
        	int l = level(x,y);
        	if(map.containsKey(l)) {
        		Integer arr[][] = map.get(l);
        		if(x==l && y<arr[1][1]) {
        			arr[1][0] = x;
        			arr[1][1] = y;
        		}
        		if(y==l && x<arr[0][0]) {
        			arr[0][0] = x;
        			arr[0][1] = y;
        		}
        	}else {
            	map.put(l, new Integer[][] {
            		{x,y},// top left
            		{x,y}// bottom right
            	});
        	}
        }
        int prevLevel = -1;
        long distancetop = 0;
        long distancebottom = 0;
        SortedSet<Integer> keys = new TreeSet<>(map.keySet());
        for(Integer key: keys) {
        	Integer arr[][] = map.get(key);
        	if(prevLevel>=0) {
	        	Integer arrPrev[][] = map.get(prevLevel);
	        	long tmpdistancetop;
	        	long tmpdistancebottom;
	        	if(distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]) >
	        		distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1])) {
		        	tmpdistancetop = distancebottom + distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1]);
	        	}else {
		        	tmpdistancetop = distancetop + distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]);
	        	}
	        	if(distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]) >
	        		distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1])) {
		        	tmpdistancebottom = distancebottom + distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1]);
	        	}else {
		        	tmpdistancebottom = distancetop + distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]);
	        	}
	        	distancetop = tmpdistancebottom + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
	        	distancebottom = tmpdistancetop + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
        	}
        	prevLevel = key;
        }
        System.out.println(distancetop<distancebottom?distancetop:distancebottom);
        in.close();
	}

	public static int level(int x, int y) {
		return Math.max(x, y);
	}

	public static long distance(long x1, long y1, long x2, long y2) {
		return Math.abs(x1-x2)+Math.abs(y1-y2);
	}
}

import java.util.*;

public class ContestE {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Map<Integer, Integer[][]> map = new HashMap<>();
    	map.put(0, new Integer[][] {
    		{0,0},// top left
    		{0,0}// bottom right
    	});
        for(int i=0;i<n;i++){
        	int x = in.nextInt();
        	int y = in.nextInt();
        	int l = level(x,y);
        	if(map.containsKey(l)) {
        		Integer arr[][] = map.get(l);
        		if(x==l && y<arr[1][1]) {
        			arr[1][0] = x;
        			arr[1][1] = y;
        		}
        		if(y==l && x<arr[0][0]) {
        			arr[0][0] = x;
        			arr[0][1] = y;
        		}
        	}else {
            	map.put(l, new Integer[][] {
            		{x,y},// top left
            		{x,y}// bottom right
            	});
        	}
        }
        int prevLevel = -1;
        long distancetop = 0;
        long distancebottom = 0;
        for(Map.Entry<Integer, Integer[][]> e :map.entrySet()) {
        	Integer arr[][] = e.getValue();
        	if(prevLevel>=0) {
	        	Integer arrPrev[][] = map.get(prevLevel);
	        	long tmpdistancetop;
	        	long tmpdistancebottom;
	        	if(distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]) >
	        		distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1])) {
		        	tmpdistancetop = distancebottom + distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1]);
	        	}else {
		        	tmpdistancetop = distancetop + distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]);
	        	}
	        	if(distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]) >
	        		distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1])) {
		        	tmpdistancebottom = distancebottom + distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1]);
	        	}else {
		        	tmpdistancebottom = distancetop + distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]);
	        	}
	        	distancetop = tmpdistancebottom + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
	        	distancebottom = tmpdistancetop + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
        	}
        	prevLevel = e.getKey();
        }
        System.out.println(distancetop<distancebottom?distancebottom:distancebottom);
        in.close();
	}

	public static void print(Integer[][] arr) {
		for(int i=0;i<arr.length;i++) {
			for(int j=0;j<arr[i].length;j++) {
				System.out.print(arr[i][j]+" ");
			}
			System.out.println();
		}
	}

	public static int level(int x, int y) {
		return Math.max(x, y);
	}

	public static long distance(int x1, int y1, int x2, int y2) {
		return ((long)Math.abs(x1-x2))+Math.abs(y1-y2);
	}
}

import java.util.*;

public class ContestE {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Map<Integer, Integer[][]> map = new HashMap<>();
    	map.put(0, new Integer[][] {
    		{0,0},// top left
    		{0,0}// bottom right
    	});
        for(int i=0;i<n;i++){
        	int x = in.nextInt();
        	int y = in.nextInt();
        	int l = level(x,y);
        	if(map.containsKey(l)) {
        		Integer arr[][] = map.get(l);
        		if(x==l && y<arr[1][1]) {
        			arr[1][0] = x;
        			arr[1][1] = y;
        		}
        		if(y==l && x<arr[0][0]) {
        			arr[0][0] = x;
        			arr[0][1] = y;
        		}
        	}else {
            	map.put(l, new Integer[][] {
            		{x,y},// top left
            		{x,y}// bottom right
            	});
        	}
        }
        int prevLevel = -1;
        long distancetop = 0;
        long distancebottom = 0;
        for(Map.Entry<Integer, Integer[][]> e :map.entrySet()) {
        	Integer arr[][] = e.getValue();
        	if(prevLevel>=0) {
	        	Integer arrPrev[][] = map.get(prevLevel);
	        	long tmpdistancetop;
	        	long tmpdistancebottom;
//	        	print(arr);
//	        	print(arrPrev);
//	        	System.out.println(distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]) +">"+
//		        		distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1]));
//	        	System.out.println(distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]) +">"+
//	        			distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1]));
	        	if(distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]) >
	        		distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1])) {
		        	tmpdistancetop = distancebottom + distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1]);
	        	}else {
		        	tmpdistancetop = distancetop + distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]);
	        	}
	        	if(distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]) >
	        		distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1])) {
		        	tmpdistancebottom = distancebottom + distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1]);
	        	}else {
		        	tmpdistancebottom = distancetop + distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]);
	        	}
	        	distancetop = tmpdistancebottom + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
	        	distancebottom = tmpdistancetop + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
//	        	System.out.println(e.getKey()+":: "+tmpdistancetop+", "+tmpdistancebottom);
        	}
        	prevLevel = e.getKey();
//        	System.out.println(e.getKey()+": "+distancetop+", "+distancebottom);
        }
        System.out.println(Math.min(distancetop,distancebottom));
        in.close();
	}

	public static void print(Integer[][] arr) {
		for(int i=0;i<arr.length;i++) {
			for(int j=0;j<arr[i].length;j++) {
				System.out.print(arr[i][j]+" ");
			}
			System.out.println();
		}
	}

	public static int level(int x, int y) {
		return Math.max(x, y);
	}

	public static int distance(int x1, int y1, int x2, int y2) {
		return Math.abs(x1-x2)+Math.abs(y1-y2);
	}
}

import java.util.*;

public class ContestE {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Map<Integer, Integer[][]> map = new HashMap<>();
    	map.put(0, new Integer[][] {
    		{0,0},// top left
    		{0,0}// bottom right
    	});
        for(int i=0;i<n;i++){
        	int x = in.nextInt();
        	int y = in.nextInt();
        	int l = level(x,y);
        	if(map.containsKey(l)) {
        		Integer arr[][] = map.get(l);
        		if(x==l && y<arr[1][1]) {
        			arr[1][0] = x;
        			arr[1][1] = y;
        		}
        		if(y==l && x<arr[0][0]) {
        			arr[0][0] = x;
        			arr[0][1] = y;
        		}
        	}else {
            	map.put(l, new Integer[][] {
            		{x,y},// top left
            		{x,y}// bottom right
            	});
        	}
        }
        int prevLevel = -1;
        long distancetop = 0;
        long distancebottom = 0;
        SortedSet<Integer> keys = new TreeSet<>(map.keySet());
        for(Integer key: keys) {
        	Integer arr[][] = map.get(key);
        	if(prevLevel>=0) {
	        	Integer arrPrev[][] = map.get(prevLevel);
	        	long tmpdistancetop =
	        			Math.min(distancebottom + distance(arr[0][0],arr[0][1],arrPrev[1][0],arrPrev[1][1]),
	        					distancetop + distance(arr[0][0],arr[0][1],arrPrev[0][0],arrPrev[0][1]));
	        	long tmpdistancebottom =
	        			Math.min(distancebottom + distance(arr[1][0],arr[1][1],arrPrev[1][0],arrPrev[1][1]),
	        					distancetop + distance(arr[1][0],arr[1][1],arrPrev[0][0],arrPrev[0][1]));
	        	distancetop = tmpdistancebottom + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
	        	distancebottom = tmpdistancetop + distance(arr[0][0],arr[0][1],arr[1][0],arr[1][1]);
        	}
        	prevLevel = key;
        }
        System.out.println(Math.min(distancebottom, distancetop));
        in.close();
	}

	public static int level(int x, int y) {
		return Math.max(x, y);
	}

	public static long distance(long x1, long y1, long x2, long y2) {
		return Math.abs(x1-x2)+Math.abs(y1-y2);
	}
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.*;
public class YA2DWalking {
    public static void main(String[] args) {
        FastScanner scanner = new FastScanner();
        int N = scanner.nextInt();
        PriorityQueue<Point> queue = new PriorityQueue<>();
        for(int i = 0; i < N; i++) {
            queue.add(new Point(scanner.nextInt(), scanner.nextInt()));
        }
        int curLevel = 0;
        int[][] dp = new int[N][2];
        for(int i = 0; i < N; i++) {
            Arrays.fill(dp[i], Integer.MAX_VALUE);
        }
        dp[0][0] = dp[0][1] = 0;
        Point[][] poi = new Point[N][2];
        poi[0][0] = new Point(0,0);
        poi[0][1] = new Point(0, 0);
        while(!queue.isEmpty()) {
            curLevel++;
            Point p1 = queue.poll();
            Point p2 = null;
            while(!queue.isEmpty() && queue.peek().level==p1.level) p2 = queue.poll();
            if (p2 == null) p2 = p1;
            poi[curLevel][0] = p1;
            poi[curLevel][1] = p2;
            dp[curLevel][0] = Math.min(dp[curLevel][0], dp[curLevel-1][1] + dist(p2, poi[curLevel-1][1]) + dist(p1, p2));
            dp[curLevel][0] = Math.min(dp[curLevel][0], dp[curLevel-1][0] + dist(p2, poi[curLevel-1][0]) + dist(p1, p2));
            dp[curLevel][1] = Math.min(dp[curLevel][1], dp[curLevel-1][1] + dist(p1, poi[curLevel-1][1]) + dist(p1, p2));
            dp[curLevel][1] = Math.min(dp[curLevel][1], dp[curLevel-1][0] + dist(p1, poi[curLevel-1][0]) + dist(p1, p2));
        }
        System.out.println(Math.min(dp[curLevel][0], dp[curLevel][1]));
    }
    public static int dist(Point a, Point b) {
        return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
    }
    public static class Point implements Comparable<Point>{
        int x, y, level;
        public Point(int xx, int yy) {
            x = xx;
            y = yy;
            level = Math.max(xx, yy);
        }
        public int compareTo(Point o) {
            if (this.level == o.level) {
                if (this.x == o.x) return Integer.compare(o.y, this.y);
                return Integer.compare(this.x, o.x);
            }
            return Integer.compare(this.level, o.level);
        }
    }
    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;
        public FastScanner(Reader in) {
            br = new BufferedReader(in);
        }
        public FastScanner() {
            this(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String readNextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
        int[] readIntArray(int n) {
            int[] a = new int[n];
            for (int idx = 0; idx < n; idx++) {
                a[idx] = nextInt();
            }
            return a;
        }
    }
}

import java.util.*;
import java.io.*;
public final class CF {
    static class Pair implements Comparable<Pair> {
        long x, y, max;
        Pair(long x, long y) {
            this.x = x;
            this.y = y;
            this.max = Math.max(x, y);
        }
        public int compareTo(Pair other) {
            return Long.compare(this.max, other.max);
        }
    }
    static long dist(Pair p1, Pair p2) {
        return Math.abs(p1.x-p2.x)+Math.abs(p1.y-p2.y);
    }
    public static void main (String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Pair[] a = new Pair[n];
        for(int i = 0; i<n; i++)
            a[i] = new Pair(sc.nextLong(), sc.nextLong());
        Arrays.sort(a);
        List<Pair> first = new ArrayList<>();
        first.add(new Pair(0, 0));
        List<List<Pair>> layer = new ArrayList<>();
        layer.add(first);
        int start = 0;
        while(start<n) {
            int end = start;
            List<Pair> li = new ArrayList<>();
            while(end<n && a[end].max==a[start].max) {
                li.add(a[end]);
                end++;
            }
            layer.add(li);
            start = end;
        }
        for(List<Pair> i: layer) {
            Collections.sort(i, new Comparator<Pair>() {
                @Override
                public int compare(Pair p1, Pair p2) {
                    if(p1.x!=p2.x)
                        return Long.compare(p1.x, p2.x);
                    return Long.compare(p1.y, p2.y);
                }
            });
        }
        int size = layer.size();
        long[][] dp = new long[size][2];
        dp[0][0] = 0;
        dp[0][1] = 0;
        for(int i = 1; i<size; i++)
            Arrays.fill(dp[i], Long.MAX_VALUE);
        for(int i = 0; i<size-1; i++) {
            Pair c0 = layer.get(i).get(0);
            int m = layer.get(i).size();
            Pair c1 = layer.get(i).get(m-1);

            Pair n0 = layer.get(i+1).get(0);
            m = layer.get(i+1).size();
            Pair n1 = layer.get(i+1).get(m-1);

            dp[i+1][0] = Math.min(dp[i+1][0], dp[i][0]+dist(c0, n1)+dist(n1, n0));
            dp[i+1][0] = Math.min(dp[i+1][0], dp[i][1]+dist(c1, n1)+dist(n1, n0));
            dp[i+1][1] = Math.min(dp[i+1][1], dp[i][0]+dist(c0, n0)+dist(n0, n1));
            dp[i+1][1] = Math.min(dp[i+1][1], dp[i][1]+dist(c1, n0)+dist(n0, n1));
        }
        System.out.println(Math.min(dp[size-1][0], dp[size-1][1]));
    }
}

import sun.reflect.generics.tree.Tree;

import java.io.*;
import java.util.*;

public class F {
    public static void main(String[] args) throws Throwable {
        MyScanner sc = new MyScanner();
        PrintWriter pw = new PrintWriter(System.out);

        int n=sc.nextInt();
        int [] x=new int [n];
        int [] y=new int [n];

        TreeSet<Integer> set=new TreeSet<>();
        HashMap<Integer,Integer> map=new HashMap();
        for(int i=0;i<n;i++){
            x[i]=sc.nextInt();
            y[i]=sc.nextInt();
            set.add(Math.max(x[i],y[i]));
        }
        int id=0;
        for(int xx : set)
            map.put(xx,id++);

        pair [] p1=new pair [id];
        pair [] p2=new pair [id];
        ArrayList<pair> [] arr=new ArrayList[id];
        for(int i=0;i<id;i++)
            arr[i]=new ArrayList<>();
        for(int i=0;i<n;i++){
            pair p=new pair(x[i],y[i]);
            int mx=Math.max(x[i],y[i]);
            mx=map.get(mx);
            arr[mx].add(p);
        }
        long [] dis=new long [id];
        for(int i=0;i<id;i++){
            for(int j=0;j<arr[i].size()-1;j++){
                dis[i]+=Math.abs(arr[i].get(j).x-arr[i].get(j+1).x);
                dis[i]+=Math.abs(arr[i].get(j).y-arr[i].get(j+1).y);
            }
            Collections.sort(arr[i]);
            p1[i]=arr[i].get(0);
            p2[i]=arr[i].get(arr[i].size()-1);
        }

        long [][] dp=new long [id+1][2];
        dp[id-1][0]=dp[id-1][1]=dis[id-1];

        for(int i=id-2;i>=0;i--){
            for(int j=0;j<2;j++){
                dp[i][j]=dis[i];
                if(j==0){
                    dp[i][j]+=Math.min(
                            Math.abs(p2[i].x-p1[i+1].x)+Math.abs(p2[i].y-p1[i+1].y)+dp[i+1][0]
                            ,Math.abs(p2[i].x-p2[i+1].x)+Math.abs(p2[i].y-p2[i+1].y)+dp[i+1][1]);
                }else{

                    dp[i][j]+=Math.min(
                            Math.abs(p1[i].x-p1[i+1].x)+Math.abs(p1[i].y-p1[i+1].y)+dp[i+1][0]
                            ,Math.abs(p1[i].x-p2[i+1].x)+Math.abs(p1[i].y-p2[i+1].y)+dp[i+1][1]);
                }
            }
        }

        pw.println(Math.min(p1[0].x+p1[0].y+dp[0][0],p2[0].x+p2[0].y+dp[0][1]));

        pw.flush();
        pw.close();
    }

    static class pair implements Comparable<pair>{
        int x,y;
        pair(int a,int b){
            x=a;
            y=b;
        }
        public int compareTo(pair p){
            if(x!=p.x)
                return x-p.x;
            return p.y-y;
        }
    }

    static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException;

import java.io.*;
import java.util.*;

public class E1066 {

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver1066D solver = new Solver1066D();
        solver.solve(inp, out);
        out.close();
    }

    static class InputReader {
        StringTokenizer tokenizer;
        InputStreamReader sReader;
        BufferedReader reader;

        InputReader(InputStream stream) {
            sReader = new InputStreamReader(stream);
            reader = new BufferedReader(sReader, 32768);
            tokenizer = null;
        }

        String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public List<Integer> intLine(int size) {
            List<Integer> ls = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                ls.add(nextInt());
            }
            return ls;
        }

        int nextC() {
            try {
                return reader.read();
            } catch (IOException e) {
                return -1;
            }
        }

        public int[] intArr(int size) {
            int[] ls = new int[size];
            for (int i = 0; i < size; i++){
                ls[i] = nextInt();
            }
            return ls;
        }
    }

    static class Solver1066D {
        HashMap<Integer, Level> hm = new HashMap<>();
        public void solve(InputReader inp, PrintWriter out) {
            int n = inp.nextInt(), i;
            for (i=0; i < n; i++){
                int x = inp.nextInt(), y = inp.nextInt();
                int lev = Math.max(x, y);
                if (!hm.containsKey(lev)) hm.put(lev, new Level(lev));
                hm.get(lev).addv(x, y);
            }
            List<Integer> existing = new ArrayList<>(hm.keySet());
            Collections.sort(existing);
            Level curr = hm.get(existing.get(0));

            Level Null = new Level(0);
            Null.next = curr;

            for (i = 1; i < existing.size(); i++){
                Level ne = hm.get(existing.get(i));
                curr.next = ne;
                curr = ne;
            }
            out.println(Null.traverse(0, 0));
//            for (i = 0; i < existing.size(); i++){
//                Level ne = hm.get(existing.get(i));
//                out.println(existing.get(i)+": "+ ne);
//            }

        }

        class Level{
            int lev, minx, miny, maxx, maxy, d=-1, d1, d2;
            Level next;
            boolean b1 = false, b2 = false;
            Level(int lev){
                this.lev = lev;
                this.minx = lev;
                this.miny = lev;
            }
            void addv(int x, int y){
                if (x > this.maxx) maxx = x;
                if (x < this.minx) minx = x;
                if (y > this.maxy) maxy = y;
                if (y < this.miny) miny = y;
            }
            int d(){
                if (this.d == -1){
                    this.d = dist(this.maxx, this.miny, this.minx, this.maxy);
                }
                return this.d;
            }
            int traverse(int x, int y){
//                System.out.println("traversing "+x+", "+y);
                if (this.next == null) return this.d();
                if (x == this.maxx && y == this.miny){
                    if (this.b1) return this.d1;

                    this.d1 = acttraverse(this.minx, this.maxy);
                    this.b1 = true;
                    return this.d1;
                }
                else if (x == this.minx && y == this.maxy){
                    if (this.b2) return this.d2;

                    this.d2 = acttraverse(this.maxx, this.miny);
                    this.b2 = true;
                    return this.d2;
                } else {
                    System.out.println("what happened");
                    return -1;
                }
            }

            int acttraverse(int x, int y){
                int d1 = this.d() + dist(this.next.maxx, this.next.miny, x, y) + this.next.traverse(this.next.maxx, this.next.miny);
                int d2 = this.d() + dist(this.next.minx, this.next.maxy, x, y) + this.next.traverse(this.next.minx, this.next.maxy);
//                System.out.println("d found "+x+", "+y+": "+d1 +", "+d2);
//                System.out.println(dist(this.next.maxx, x, this.next.miny, y)+", "+ this.next.traverse(this.next.maxx, this.next.miny));
//                System.out.println(dist(this.next.minx, x, this.next.maxy, y) +", "+ this.next.traverse(this.next.minx, this.next.maxy));
                return Math.min(d1, d2);

            }

            @Override
            public String toString() {
                return "minx:"+this.minx+", maxx:"+this.maxx+", miny:"+this.miny+", maxy:"+this.maxy+", d:"+this.d();
            }
        }

        int dist(int x1, int y1, int x2, int y2){
            return Math.abs(x1-x2)+Math.abs(y1-y2);
        }
    }
}

import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException;

import java.io.*;
import java.util.*;

public class E1066 {

    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver1066D solver = new Solver1066D();
        solver.solve(inp, out);
        out.close();
    }

    static class InputReader {
        StringTokenizer tokenizer;
        InputStreamReader sReader;
        BufferedReader reader;

        InputReader(InputStream stream) {
            sReader = new InputStreamReader(stream);
            reader = new BufferedReader(sReader, 32768);
            tokenizer = null;
        }

        String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public List<Integer> intLine(int size) {
            List<Integer> ls = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                ls.add(nextInt());
            }
            return ls;
        }

        int nextC() {
            try {
                return reader.read();
            } catch (IOException e) {
                return -1;
            }
        }

        public int[] intArr(int size) {
            int[] ls = new int[size];
            for (int i = 0; i < size; i++){
                ls[i] = nextInt();
            }
            return ls;
        }
    }

    static class Solver1066D {
        HashMap<Integer, Level> hm = new HashMap<>();
        public void solve(InputReader inp, PrintWriter out) {
            int n = inp.nextInt(), i;
            for (i=0; i < n; i++){
                int x = inp.nextInt(), y = inp.nextInt();
                int lev = Math.max(x, y);
                if (!hm.containsKey(lev)) hm.put(lev, new Level(lev));
                hm.get(lev).addv(x, y);
            }
            List<Integer> existing = new ArrayList<>(hm.keySet());
            Collections.sort(existing);

            Level Null = new Level(0);
            Level curr = Null;

            for (i = 0; i < existing.size(); i++){
                Level ne = hm.get(existing.get(i));
                curr.next = ne;
                curr = ne;
            }
            out.println(Null.traverse(0, 0));
//            for (i = 0; i < existing.size(); i++){
//                Level ne = hm.get(existing.get(i));
//                out.println(existing.get(i)+": "+ ne);
//            }

        }

        class Level{
            int lev, minx, miny, maxx, maxy, d=-1;
            long d1, d2;
            Level next;
            boolean b1 = false, b2 = false;
            Level(int lev){
                this.lev = lev;
                this.minx = lev;
                this.miny = lev;
            }
            void addv(int x, int y){
                if (x > this.maxx) maxx = x;
                if (x < this.minx) minx = x;
                if (y > this.maxy) maxy = y;
                if (y < this.miny) miny = y;
            }
            int d(){
                if (this.d == -1){
                    this.d = dist(this.maxx, this.miny, this.minx, this.maxy);
                }
                return this.d;
            }
            long traverse(int x, int y){
//                System.out.println("traversing "+x+", "+y);
                if (this.next == null) return this.d();
                if (x == this.maxx && y == this.miny){
                    if (this.b1) return this.d1;

                    this.d1 = this.d()+acttraverse(this.minx, this.maxy);
                    this.b1 = true;
                    return this.d1;
                }
                else if (x == this.minx && y == this.maxy){
                    if (this.b2) return this.d2;

                    this.d2 = this.d()+acttraverse(this.maxx, this.miny);
                    this.b2 = true;
                    return this.d2;
                } else {
                    System.out.println("what happened");
                    return -1;
                }
            }

            long acttraverse(int x, int y){
                long d1 = dist(this.next.maxx, this.next.miny, x, y) + this.next.traverse(this.next.maxx, this.next.miny);
                long d2 = dist(this.next.minx, this.next.maxy, x, y) + this.next.traverse(this.next.minx, this.next.maxy);
                System.out.println("d found "+x+", "+y+": "+d1 +", "+d2);
                System.out.println(dist(this.next.maxx, this.next.miny, x, y)+", "+ this.next.traverse(this.next.maxx, this.next.miny));
                System.out.println(dist(this.next.minx, this.next.maxy, x, y) +", "+ this.next.traverse(this.next.minx, this.next.maxy));
                return Math.min(d1, d2);
            }

            @Override
            public String toString() {
                return "minx:"+this.minx+", maxx:"+this.maxx+", miny:"+this.miny+", maxy:"+this.maxy+", d:"+this.d();
            }
        }

        int dist(int x1, int y1, int x2, int y2){
            return Math.abs(x1-x2)+Math.abs(y1-y2);
        }
    }
}

import java.io.*;
import java.math.BigInteger;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class F_515
{
	public static final long[] POWER2 = generatePOWER2();
	public static final IteratorBuffer<Long> ITERATOR_BUFFER_PRIME = new IteratorBuffer<>(streamPrime(1000000).iterator());
	public static long BIG = 1000000000 + 7;
	private static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
	private static StringTokenizer stringTokenizer = null;
	private static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

	static class Array<Type>
		implements Iterable<Type>
	{
		private final Object[] array;

		public Array(int size)
		{
			this.array = new Object[size];
		}

		public Array(
			int size,
			Type element
		)
		{
			this(size);
			Arrays.fill(
				this.array,
				element
			);
		}

		public Array(
			Array<Type> array,
			Type element
		)
		{
			this(array.size() + 1);
			for (int index = 0; index < array.size(); index++)
			{
				set(
					index,
					array.get(index)
				);
			}
			set(
				size() - 1,
				element
			);
		}

		public Array(List<Type> list)
		{
			this(list.size());
			int index = 0;
			for (Type element : list)
			{
				set(
					index,
					element
				);
				index += 1;
			}
		}

		public Type get(int index)
		{
			return (Type) this.array[index];
		}

		@Override
		public Iterator<Type> iterator()
		{
			return new Iterator<Type>()
			{
				int index = 0;

				@Override
				public boolean hasNext()
				{
					return this.index < size();
				}

				@Override
				public Type next()
				{
					Type result = Array.this.get(index);
					index += 1;
					return result;
				}
			};
		}

		public Array set(
			int index,
			Type value
		)
		{
			this.array[index] = value;
			return this;
		}

		public int size()
		{
			return this.array.length;
		}

		public List<Type> toList()
		{
			List<Type> result = new ArrayList<>();
			for (Type element : this)
			{
				result.add(element);
			}
			return result;
		}

		@Override
		public String toString()
		{
			return "[" + F_515.toString(
				this,
				", "
			) + "]";
		}
	}

	static class BIT
	{
		private static int lastBit(int index)
		{
			return index & -index;
		}

		private final long[] tree;

		public BIT(int size)
		{
			this.tree = new long[size];
		}

		public void add(
			int index,
			long delta
		)
		{
			index += 1;
			while (index <= this.tree.length)
			{
				tree[index - 1] += delta;
				index += lastBit(index);
			}
		}

		public long prefix(int end)
		{
			long result = 0;
			while (end > 0)
			{
				result += this.tree[end - 1];
				end -= lastBit(end);
			}
			return result;
		}

		public int size()
		{
			return this.tree.length;
		}

		public long sum(
			int start,
			int end
		)
		{
			return prefix(end) - prefix(start);
		}
	}

	static abstract class Edge<TypeVertex extends Vertex<TypeVertex, TypeEdge>, TypeEdge extends Edge<TypeVertex, TypeEdge>>
	{
		public final TypeVertex vertex0;
		public final TypeVertex vertex1;
		public final boolean bidirectional;

		public Edge(
			TypeVertex vertex0,
			TypeVertex vertex1,
			boolean bidirectional
		)
		{
			this.vertex0 = vertex0;
			this.vertex1 = vertex1;
			this.bidirectional = bidirectional;
			this.vertex0.edges.add(getThis());
			if (this.bidirectional)
			{
				this.vertex1.edges.add(getThis());
			}
		}

		public abstract TypeEdge getThis();

		public TypeVertex other(Vertex<TypeVertex, TypeEdge> vertex)
		{
			TypeVertex result;
			if (vertex0 == vertex)
			{
				result = vertex1;
			}
			else
			{
				result = vertex0;
			}
			return result;
		}

		public void remove()
		{
			this.vertex0.edges.remove(getThis());
			if (this.bidirectional)
			{
				this.vertex1.edges.remove(getThis());
			}
		}

		@Override
		public String toString()
		{
			return this.vertex0 + "->" + this.vertex1;
		}
	}

	public static class EdgeDefault<TypeVertex extends Vertex<TypeVertex, EdgeDefault<TypeVertex>>>
		extends Edge<TypeVertex, EdgeDefault<TypeVertex>>
	{
		public EdgeDefault(
			TypeVertex vertex0,
			TypeVertex vertex1,
			boolean bidirectional
		)
		{
			super(
				vertex0,
				vertex1,
				bidirectional
			);
		}

		@Override
		public EdgeDefault<TypeVertex> getThis()
		{
			return this;
		}
	}

	public static class EdgeDefaultDefault
		extends Edge<VertexDefaultDefault, EdgeDefaultDefault>
	{
		public EdgeDefaultDefault(
			VertexDefaultDefault vertex0,
			VertexDefaultDefault vertex1,
			boolean bidirectional
		)
		{
			super(
				vertex0,
				vertex1,
				bidirectional
			);
		}

		@Override
		public EdgeDefaultDefault getThis()
		{
			return this;
		}
	}

	public static class FIFO<Type>
	{
		public SingleLinkedList<Type> start;
		public SingleLinkedList<Type> end;

		public FIFO()
		{
			this.start = null;
			this.end = null;
		}

		public boolean isEmpty()
		{
			return this.start == null;
		}

		public Type peek()
		{
			return this.start.element;
		}

		public Type pop()
		{
			Type result = this.start.element;
			this.start = this.start.next;
			return result;
		}

		public void push(Type element)
		{
			SingleLinkedList<Type> list = new SingleLinkedList<>(
				element,
				null
			);
			if (this.start == null)
			{
				this.start = list;
				this.end = list;
			}
			else
			{
				this.end.next = list;
				this.end = list;
			}
		}
	}

	static class Fraction
		implements Comparable<Fraction>
	{
		public static final Fraction ZERO = new Fraction(
			0,
			1
		);

		public static Fraction fraction(long whole)
		{
			return fraction(
				whole,
				1
			);
		}

		public static Fraction fraction(
			long numerator,
			long denominator
		)
		{
			Fraction result;
			if (denominator == 0)
			{
				throw new ArithmeticException();
			}
			if (numerator == 0)
			{
				result = Fraction.ZERO;
			}
			else
			{
				int sign;
				if (numerator < 0 ^ denominator < 0)
				{
					sign = -1;
					numerator = Math.abs(numerator);
					denominator = Math.abs(denominator);
				}
				else
				{
					sign = 1;
				}
				long gcd = gcd(
					numerator,
					denominator
				);
				result = new Fraction(
					sign * numerator / gcd,
					denominator / gcd
				);
			}
			return result;
		}

		public final long numerator;
		public final long denominator;

		private Fraction(
			long numerator,
			long denominator
		)
		{
			this.numerator = numerator;
			this.denominator = denominator;
		}

		public Fraction add(Fraction fraction)
		{
			return fraction(
				this.numerator * fraction.denominator + fraction.numerator * this.denominator,
				this.denominator * fraction.denominator
			);
		}

		@Override
		public int compareTo(Fraction that)
		{
			return Long.compare(
				this.numerator * that.denominator,
				that.numerator * this.denominator
			);
		}

		public Fraction divide(Fraction fraction)
		{
			return multiply(fraction.inverse());
		}

		public boolean equals(Fraction that)
		{
			return this.compareTo(that) == 0;
		}

		public boolean equals(Object that)
		{
			return this.compareTo((Fraction) that) == 0;
		}

		public Fraction getRemainder()
		{
			return fraction(
				this.numerator - getWholePart() * denominator,
				denominator
			);
		}

		public long getWholePart()
		{
			return this.numerator / this.denominator;
		}

		public Fraction inverse()
		{
			return fraction(
				this.denominator,
				this.numerator
			);
		}

		public Fraction multiply(Fraction fraction)
		{
			return fraction(
				this.numerator * fraction.numerator,
				this.denominator * fraction.denominator
			);
		}

		public Fraction neg()
		{
			return fraction(
				-this.numerator,
				this.denominator
			);
		}

		public Fraction sub(Fraction fraction)
		{
			return add(fraction.neg());
		}

		@Override
		public String toString()
		{
			String result;
			if (getRemainder().equals(Fraction.ZERO))
			{
				result = "" + this.numerator;
			}
			else
			{
				result = this.numerator + "/" + this.denominator;
			}
			return result;
		}
	}

	static class IteratorBuffer<Type>
	{
		private Iterator<Type> iterator;
		private List<Type> list;

		public IteratorBuffer(Iterator<Type> iterator)
		{
			this.iterator = iterator;
			this.list = new ArrayList<Type>();
		}

		public Iterator<Type> iterator()
		{
			return new Iterator<Type>()
			{
				int index = 0;

				@Override
				public boolean hasNext()
				{
					return this.index < list.size() || IteratorBuffer.this.iterator.hasNext();
				}

				@Override
				public Type next()
				{
					if (list.size() <= this.index)
					{
						list.add(iterator.next());
					}
					Type result = list.get(index);
					index += 1;
					return result;
				}
			};
		}
	}

	public static class MapCount<Type>
		extends SortedMapAVL<Type, Long>
	{
		private int count;

		public MapCount(Comparator<? super Type> comparator)
		{
			super(comparator);
			this.count = 0;
		}

		public long add(
			Type key,
			Long delta
		)
		{
			long result;
			if (delta > 0)
			{
				Long value = get(key);
				if (value == null)
				{
					value = delta;
				}
				else
				{
					value += delta;
				}
				put(
					key,
					value
				);
				result = delta;
			}
			else
			{
				result = 0;
			}
			this.count += result;
			return result;
		}

		public int count()
		{
			return this.count;
		}

		public List<Type> flatten()
		{
			List<Type> result = new ArrayList<>();
			for (Entry<Type, Long> entry : entrySet())
			{
				for (long index = 0; index < entry.getValue(); index++)
				{
					result.add(entry.getKey());
				}
			}
			return result;
		}

		@Override
		public SortedMapAVL<Type, Long> headMap(Type keyEnd)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public void putAll(Map<? extends Type, ? extends Long> map)
		{
			throw new UnsupportedOperationException();
		}

		public long remove(
			Type key,
			Long delta
		)
		{
			long result;
			if (delta > 0)
			{
				Long value = get(key) - delta;
				if (value <= 0)
				{
					result = delta + value;
					remove(key);
				}
				else
				{
					result = delta;
					put(
						key,
						value
					);
				}
			}
			else
			{
				result = 0;
			}
			this.count -= result;
			return result;
		}

		@Override
		public Long remove(Object key)
		{
			Long result = super.remove(key);
			this.count -= result;
			return result;
		}

		@Override
		public SortedMapAVL<Type, Long> subMap(
			Type keyStart,
			Type keyEnd
		)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public SortedMapAVL<Type, Long> tailMap(Type keyStart)
		{
			throw new UnsupportedOperationException();
		}
	}

	public static class MapSet<TypeKey, TypeValue>
		extends SortedMapAVL<TypeKey, SortedSetAVL<TypeValue>>
		implements Iterable<TypeValue>
	{
		private Comparator<? super TypeValue> comparatorValue;

		public MapSet(
			Comparator<? super TypeKey> comparatorKey,
			Comparator<? super TypeValue> comparatorValue
		)
		{
			super(comparatorKey);
			this.comparatorValue = comparatorValue;
		}

		public MapSet(
			Comparator<? super TypeKey> comparatorKey,
			SortedSetAVL<Entry<TypeKey, SortedSetAVL<TypeValue>>> entrySet,
			Comparator<? super TypeValue> comparatorValue
		)
		{
			super(
				comparatorKey,
				entrySet
			);
			this.comparatorValue = comparatorValue;
		}

		public boolean add(
			TypeKey key,
			TypeValue value
		)
		{
			SortedSetAVL<TypeValue> set = computeIfAbsent(
				key,
				k -> new SortedSetAVL<>(comparatorValue)
			);
			return set.add(value);
		}

		public TypeValue firstValue()
		{
			TypeValue result;
			Entry<TypeKey, SortedSetAVL<TypeValue>> firstEntry = firstEntry();
			if (firstEntry == null)
			{
				result = null;
			}
			else
			{
				result = firstEntry.getValue().first();
			}
			return result;
		}

		@Override
		public MapSet<TypeKey, TypeValue> headMap(TypeKey keyEnd)
		{
			return new MapSet<>(
				this.comparator,
				this.entrySet.headSet(new AbstractMap.SimpleEntry<>(
					keyEnd,
					null
				)),
				this.comparatorValue
			);
		}

		public Iterator<TypeValue> iterator()
		{
			return new Iterator<TypeValue>()
			{
				Iterator<SortedSetAVL<TypeValue>> iteratorValues = values().iterator();
				Iterator<TypeValue> iteratorValue = null;

				@Override
				public boolean hasNext()
				{
					return iteratorValues.hasNext() || (iteratorValue != null && iteratorValue.hasNext());
				}

				@Override
				public TypeValue next()
				{
					if (iteratorValue == null || !iteratorValue.hasNext())
					{
						iteratorValue = iteratorValues.next().iterator();
					}
					return iteratorValue.next();
				}
			};
		}

		public TypeValue lastValue()
		{
			TypeValue result;
			Entry<TypeKey, SortedSetAVL<TypeValue>> lastEntry = lastEntry();
			if (lastEntry == null)
			{
				result = null;
			}
			else
			{
				result = lastEntry.getValue().last();
			}
			return result;
		}

		public boolean removeSet(
			TypeKey key,
			TypeValue value
		)
		{
			boolean result;
			SortedSetAVL<TypeValue> set = get(key);
			if (set == null)
			{
				result = false;
			}
			else
			{
				result = set.remove(value);
				if (set.size() == 0)
				{
					remove(key);
				}
			}
			return result;
		}

		@Override
		public MapSet<TypeKey, TypeValue> tailMap(TypeKey keyStart)
		{
			return new MapSet<>(
				this.comparator,
				this.entrySet.tailSet(new AbstractMap.SimpleEntry<>(
					keyStart,
					null
				)),
				this.comparatorValue
			);
		}
	}

	public static class Matrix
	{
		public final int rows;
		public final int columns;
		public final Fraction[][] cells;

		public Matrix(
			int rows,
			int columns
		)
		{
			this.rows = rows;
			this.columns = columns;
			this.cells = new Fraction[rows][columns];
			for (int row = 0; row < rows; row++)
			{
				for (int column = 0; column < columns; column++)
				{
					set(
						row,
						column,
						Fraction.ZERO
					);
				}
			}
		}

		public void add(
			int rowSource,
			int rowTarget,
			Fraction fraction
		)
		{
			for (int column = 0; column < columns; column++)
			{
				this.cells[rowTarget][column] = this.cells[rowTarget][column].add(this.cells[rowSource][column].multiply(fraction));
			}
		}

		private int columnPivot(int row)
		{
			int result = this.columns;
			for (int column = this.columns - 1; 0 <= column; column--)
			{
				if (this.cells[row][column].compareTo(Fraction.ZERO) != 0)
				{
					result = column;
				}
			}
			return result;
		}

		public void reduce()
		{
			for (int rowMinimum = 0; rowMinimum < this.rows; rowMinimum++)
			{
				int rowPivot = rowPivot(rowMinimum);
				if (rowPivot != -1)
				{
					int columnPivot = columnPivot(rowPivot);
					Fraction current = this.cells[rowMinimum][columnPivot];
					Fraction pivot = this.cells[rowPivot][columnPivot];
					Fraction fraction = pivot.inverse().sub(current.divide(pivot));
					add(
						rowPivot,
						rowMinimum,
						fraction
					);
					for (int row = rowMinimum + 1; row < this.rows; row++)
					{
						if (columnPivot(row) == columnPivot)
						{
							add(
								rowMinimum,
								row,
								this.cells[row][columnPivot(row)].neg()
							);
						}
					}
				}
			}
		}

		private int rowPivot(int rowMinimum)
		{
			int result = -1;
			int pivotColumnMinimum = this.columns;
			for (int row = rowMinimum; row < this.rows; row++)
			{
				int pivotColumn = columnPivot(row);
				if (pivotColumn < pivotColumnMinimum)
				{
					result = row;
					pivotColumnMinimum = pivotColumn;
				}
			}
			return result;
		}

		public void set(
			int row,
			int column,
			Fraction value
		)
		{
			this.cells[row][column] = value;
		}

		public String toString()
		{
			String result = "";
			for (int row = 0; row < rows; row++)
			{
				for (int column = 0; column < columns; column++)
				{
					result += this.cells[row][column] + "\t";
				}
				result += "\n";
			}
			return result;
		}
	}

	public static class Node<Type>
	{
		public static <Type> Node<Type> balance(Node<Type> result)
		{
			while (result != null && 1 < Math.abs(height(result.left) - height(result.right)))
			{
				if (height(result.left) < height(result.right))
				{
					Node<Type> right = result.right;
					if (height(right.right) < height(right.left))
					{
						result = new Node<>(
							result.value,
							result.left,
							right.rotateRight()
						);
					}
					result = result.rotateLeft();
				}
				else
				{
					Node<Type> left = result.left;
					if (height(left.left) < height(left.right))
					{
						result = new Node<>(
							result.value,
							left.rotateLeft(),
							result.right
						);
					}
					result = result.rotateRight();
				}
			}
			return result;
		}

		public static <Type> Node<Type> clone(Node<Type> result)
		{
			if (result != null)
			{
				result = new Node<>(
					result.value,
					clone(result.left),
					clone(result.right)
				);
			}
			return result;
		}

		public static <Type> Node<Type> delete(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					if (node.left == null)
					{
						result = node.right;
					}
					else
					{
						if (node.right == null)
						{
							result = node.left;
						}
						else
						{
							Node<Type> first = first(node.right);
							result = new Node<>(
								first.value,
								node.left,
								delete(
									node.right,
									first.value,
									comparator
								)
							);
						}
					}
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							delete(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							delete(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> Node<Type> first(Node<Type> result)
		{
			while (result.left != null)
			{
				result = result.left;
			}
			return result;
		}

		public static <Type> Node<Type> get(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = node;
				}
				else
				{
					if (compare < 0)
					{
						result = get(
							node.left,
							value,
							comparator
						);
					}
					else
					{
						result = get(
							node.right,
							value,
							comparator
						);
					}
				}
			}
			return result;
		}

		public static <Type> Node<Type> head(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = node.left;
				}
				else
				{
					if (compare < 0)
					{
						result = head(
							node.left,
							value,
							comparator
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							head(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static int height(Node node)
		{
			return node == null ? 0 : node.height;
		}

		public static <Type> Node<Type> insert(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = new Node<>(
					value,
					null,
					null
				);
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = new Node<>(
						value,
						node.left,
						node.right
					);
					;
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							insert(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							insert(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> Node<Type> last(Node<Type> result)
		{
			while (result.right != null)
			{
				result = result.right;
			}
			return result;
		}

		public static int size(Node node)
		{
			return node == null ? 0 : node.size;
		}

		public static <Type> Node<Type> tail(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = new Node<>(
						node.value,
						null,
						node.right
					);
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							tail(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = tail(
							node.right,
							value,
							comparator
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> void traverseOrderIn(
			Node<Type> node,
			Consumer<Type> consumer
		)
		{
			if (node != null)
			{
				traverseOrderIn(
					node.left,
					consumer
				);
				consumer.accept(node.value);
				traverseOrderIn(
					node.right,
					consumer
				);
			}
		}

		public final Type value;
		public final Node<Type> left;
		public final Node<Type> right;
		public final int size;
		private final int height;

		public Node(
			Type value,
			Node<Type> left,
			Node<Type> right
		)
		{
			this.value = value;
			this.left = left;
			this.right = right;
			this.size = 1 + size(left) + size(right);
			this.height = 1 + Math.max(
				height(left),
				height(right)
			);
		}

		public Node<Type> rotateLeft()
		{
			Node<Type> left = new Node<>(
				this.value,
				this.left,
				this.right.left
			);
			return new Node<>(
				this.right.value,
				left,
				this.right.right
			);
		}

		public Node<Type> rotateRight()
		{
			Node<Type> right = new Node<>(
				this.value,
				this.left.right,
				this.right
			);
			return new Node<>(
				this.left.value,
				this.left.left,
				right
			);
		}
	}

	public static class SingleLinkedList<Type>
	{
		public final Type element;
		public SingleLinkedList<Type> next;

		public SingleLinkedList(
			Type element,
			SingleLinkedList<Type> next
		)
		{
			this.element = element;
			this.next = next;
		}

		public void toCollection(Collection<Type> collection)
		{
			if (this.next != null)
			{
				this.next.toCollection(collection);
			}
			collection.add(this.element);
		}
	}

	public static class SmallSetIntegers
	{
		public static final int SIZE = 20;
		public static final int[] SET = generateSet();
		public static final int[] COUNT = generateCount();
		public static final int[] INTEGER = generateInteger();

		private static int count(int set)
		{
			int result = 0;
			for (int integer = 0; integer < SIZE; integer++)
			{
				if (0 < (set & set(integer)))
				{
					result += 1;
				}
			}
			return result;
		}

		private static final int[] generateCount()
		{
			int[] result = new int[1 << SIZE];
			for (int set = 0; set < result.length; set++)
			{
				result[set] = count(set);
			}
			return result;
		}

		private static final int[] generateInteger()
		{
			int[] result = new int[1 << SIZE];
			Arrays.fill(
				result,
				-1
			);
			for (int integer = 0; integer < SIZE; integer++)
			{
				result[SET[integer]] = integer;
			}
			return result;
		}

		private static final int[] generateSet()
		{
			int[] result = new int[SIZE];
			for (int integer = 0; integer < result.length; integer++)
			{
				result[integer] = set(integer);
			}
			return result;
		}

		private static int set(int integer)
		{
			return 1 << integer;
		}
	}

	public static class SortedMapAVL<TypeKey, TypeValue>
		implements SortedMap<TypeKey, TypeValue>
	{
		public final Comparator<? super TypeKey> comparator;
		public final SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet;

		public SortedMapAVL(Comparator<? super TypeKey> comparator)
		{
			this(
				comparator,
				new SortedSetAVL<>((entry0, entry1) -> comparator.compare(
					entry0.getKey(),
					entry1.getKey()
				))
			);
		}

		private SortedMapAVL(
			Comparator<? super TypeKey> comparator,
			SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet
		)
		{
			this.comparator = comparator;
			this.entrySet = entrySet;
		}

		@Override
		public void clear()
		{
			this.entrySet.clear();
		}

		@Override
		public Comparator<? super TypeKey> comparator()
		{
			return this.comparator;
		}

		@Override
		public boolean containsKey(Object key)
		{
			return this.entrySet().contains(new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			));
		}

		@Override
		public boolean containsValue(Object value)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet()
		{
			return this.entrySet;
		}

		public Entry<TypeKey, TypeValue> firstEntry()
		{
			return this.entrySet.first();
		}

		@Override
		public TypeKey firstKey()
		{
			return firstEntry().getKey();
		}

		@Override
		public TypeValue get(Object key)
		{
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			);
			entry = this.entrySet.get(entry);
			return entry == null ? null : entry.getValue();
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> headMap(TypeKey keyEnd)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.headSet(new AbstractMap.SimpleEntry<>(
					keyEnd,
					null
				))
			);
		}

		@Override
		public boolean isEmpty()
		{
			return this.entrySet.isEmpty();
		}

		@Override
		public Set<TypeKey> keySet()
		{
			return new SortedSet<TypeKey>()
			{
				@Override
				public boolean add(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean addAll(Collection<? extends TypeKey> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public void clear()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public Comparator<? super TypeKey> comparator()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean contains(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean containsAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public TypeKey first()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public SortedSet<TypeKey> headSet(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean isEmpty()
				{
					return size() == 0;
				}

				@Override
				public Iterator<TypeKey> iterator()
				{
					final Iterator<Entry<TypeKey, TypeValue>> iterator = SortedMapAVL.this.entrySet.iterator();
					return new Iterator<TypeKey>()
					{
						@Override
						public boolean hasNext()
						{
							return iterator.hasNext();
						}

						@Override
						public TypeKey next()
						{
							return iterator.next().getKey();
						}
					};
				}

				@Override
				public TypeKey last()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean remove(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean removeAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean retainAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public int size()
				{
					return SortedMapAVL.this.entrySet.size();
				}

				@Override
				public SortedSet<TypeKey> subSet(
					TypeKey typeKey,
					TypeKey e1
				)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public SortedSet<TypeKey> tailSet(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public Object[] toArray()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public <T> T[] toArray(T[] ts)
				{
					throw new UnsupportedOperationException();
				}
			};
		}

		public Entry<TypeKey, TypeValue> lastEntry()
		{
			return this.entrySet.last();
		}

		@Override
		public TypeKey lastKey()
		{
			return lastEntry().getKey();
		}

		@Override
		public TypeValue put(
			TypeKey key,
			TypeValue value
		)
		{
			TypeValue result = get(key);
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				key,
				value
			);
			this.entrySet().add(entry);
			return result;
		}

		@Override
		public void putAll(Map<? extends TypeKey, ? extends TypeValue> map)
		{
			map.entrySet()
				.forEach(entry -> put(
					entry.getKey(),
					entry.getValue()
				));
		}

		@Override
		public TypeValue remove(Object key)
		{
			TypeValue result = get(key);
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			);
			this.entrySet.remove(entry);
			return result;
		}

		@Override
		public int size()
		{
			return this.entrySet().size();
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> subMap(
			TypeKey keyStart,
			TypeKey keyEnd
		)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.subSet(
					new AbstractMap.SimpleEntry<>(
						keyStart,
						null
					),
					new AbstractMap.SimpleEntry<>(
						keyEnd,
						null
					)
				)
			);
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> tailMap(TypeKey keyStart)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.tailSet(new AbstractMap.SimpleEntry<>(
					keyStart,
					null
				))
			);
		}

		@Override
		public String toString()
		{
			return this.entrySet().toString();
		}

		@Override
		public Collection<TypeValue> values()
		{
			return new Collection<TypeValue>()
			{
				@Override
				public boolean add(TypeValue typeValue)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean addAll(Collection<? extends TypeValue> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public void clear()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean contains(Object value)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean containsAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean isEmpty()
				{
					return SortedMapAVL.this.entrySet.isEmpty();
				}

				@Override
				public Iterator<TypeValue> iterator()
				{
					return new Iterator<TypeValue>()
					{
						Iterator<Entry<TypeKey, TypeValue>> iterator = SortedMapAVL.this.entrySet.iterator();

						@Override
						public boolean hasNext()
						{
							return this.iterator.hasNext();
						}

						@Override
						public TypeValue next()
						{
							return this.iterator.next().getValue();
						}
					};
				}

				@Override
				public boolean remove(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean removeAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean retainAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public int size()
				{
					return SortedMapAVL.this.entrySet.size();
				}

				@Override
				public Object[] toArray()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public <T> T[] toArray(T[] ts)
				{
					throw new UnsupportedOperationException();
				}
			};
		}
	}

	public static class SortedSetAVL<Type>
		implements SortedSet<Type>
	{
		public Comparator<? super Type> comparator;
		public Node<Type> root;

		private SortedSetAVL(
			Comparator<? super Type> comparator,
			Node<Type> root
		)
		{
			this.comparator = comparator;
			this.root = root;
		}

		public SortedSetAVL(Comparator<? super Type> comparator)
		{
			this(
				comparator,
				null
			);
		}

		public SortedSetAVL(
			Collection<? extends Type> collection,
			Comparator<? super Type> comparator
		)
		{
			this(
				comparator,
				null
			);
			this.addAll(collection);
		}

		public SortedSetAVL(SortedSetAVL<Type> sortedSetAVL)
		{
			this(
				sortedSetAVL.comparator,
				Node.clone(sortedSetAVL.root)
			);
		}

		@Override
		public boolean add(Type value)
		{
			int sizeBefore = size();
			this.root = Node.insert(
				this.root,
				value,
				this.comparator
			);
			return sizeBefore != size();
		}

		@Override
		public boolean addAll(Collection<? extends Type> collection)
		{
			return collection.stream()
				.map(this::add)
				.reduce(
					true,
					(x, y) -> x | y
				);
		}

		@Override
		public void clear()
		{
			this.root = null;
		}

		@Override
		public Comparator<? super Type> comparator()
		{
			return this.comparator;
		}

		@Override
		public boolean contains(Object value)
		{
			return Node.get(
				this.root,
				(Type) value,
				this.comparator
			) != null;
		}

		@Override
		public boolean containsAll(Collection<?> collection)
		{
			return collection.stream()
				.allMatch(this::contains);
		}

		@Override
		public Type first()
		{
			return Node.first(this.root).value;
		}

		public Type get(Type value)
		{
			Node<Type> node = Node.get(
				this.root,
				value,
				this.comparator
			);
			return node == null ? null : node.value;
		}

		@Override
		public SortedSetAVL<Type> headSet(Type valueEnd)
		{
			return new SortedSetAVL<>(
				this.comparator,
				Node.head(
					this.root,
					valueEnd,
					this.comparator
				)
			);
		}

		@Override
		public boolean isEmpty()
		{
			return this.root == null;
		}

		@Override
		public Iterator<Type> iterator()
		{
			Stack<Node<Type>> path = new Stack<>();
			return new Iterator<Type>()
			{
				{
					push(SortedSetAVL.this.root);
				}

				@Override
				public boolean hasNext()
				{
					return !path.isEmpty();
				}

				@Override
				public Type next()
				{
					if (path.isEmpty())
					{
						throw new NoSuchElementException();
					}
					else
					{
						Node<Type> node = path.peek();
						Type result = node.value;
						if (node.right != null)
						{
							push(node.right);
						}
						else
						{
							do
							{
								node = path.pop();
							}
							while (!path.isEmpty() && path.peek().right == node);
						}
						return result;
					}
				}

				public void push(Node<Type> node)
				{
					while (node != null)
					{
						path.push(node);
						node = node.left;
					}
				}
			};
		}

		@Override
		public Type last()
		{
			return Node.last(this.root).value;
		}

		@Override
		public boolean remove(Object value)
		{
			int sizeBefore = size();
			this.root = Node.delete(
				this.root,
				(Type) value,
				this.comparator
			);
			return sizeBefore != size();
		}

		@Override
		public boolean removeAll(Collection<?> collection)
		{
			return collection.stream()
				.map(this::remove)
				.reduce(
					true,
					(x, y) -> x | y
				);
		}

		@Override
		public boolean retainAll(Collection<?> collection)
		{
			SortedSetAVL<Type> set = new SortedSetAVL<>(this.comparator);
			collection.stream()
				.map(element -> (Type) element)
				.filter(this::contains)
				.forEach(set::add);
			boolean result = size() != set.size();
			this.root = set.root;
			return result;
		}

		@Override
		public int size()
		{
			return this.root == null ? 0 : this.root.size;
		}

		@Override
		public SortedSetAVL<Type> subSet(
			Type valueStart,
			Type valueEnd
		)
		{
			return tailSet(valueStart).headSet(valueEnd);
		}

		@Override
		public SortedSetAVL<Type> tailSet(Type valueStart)
		{
			return new SortedSetAVL<>(
				this.comparator,
				Node.tail(
					this.root,
					valueStart,
					this.comparator
				)
			);
		}

		@Override
		public Object[] toArray()
		{
			return toArray(new Object[0]);
		}

		@Override
		public <T> T[] toArray(T[] ts)
		{
			List<Object> list = new ArrayList<>();
			Node.traverseOrderIn(
				this.root,
				list::add
			);
			return list.toArray(ts);
		}

		@Override
		public String toString()
		{
			return "{" + F_515.toString(
				this,
				", "
			) + "}";
		}
	}

	public static class Tree2D
	{
		public static final int SIZE = 1 << 30;
		public static final Tree2D[] TREES_NULL = new Tree2D[] { null, null, null, null };

		public static boolean contains(
			int x,
			int y,
			int left,
			int bottom,
			int size
		)
		{
			return left <= x && x < left + size && bottom <= y && y < bottom + size;
		}

		public static int count(Tree2D[] trees)
		{
			int result = 0;
			for (int index = 0; index < 4; index++)
			{
				if (trees[index] != null)
				{
					result += trees[index].count;
				}
			}
			return result;
		}

		public static int count
			(
				int rectangleLeft,
				int rectangleBottom,
				int rectangleRight,
				int rectangleTop,
				Tree2D tree,
				int left,
				int bottom,
				int size
			)
		{
			int result;
			if (tree == null)
			{
				result = 0;
			}
			else
			{
				int right = left + size;
				int top = bottom + size;
				int intersectionLeft = Math.max(
					rectangleLeft,
					left
				);
				int intersectionBottom = Math.max(
					rectangleBottom,
					bottom
				);
				int intersectionRight = Math.min(
					rectangleRight,
					right
				);
				int intersectionTop = Math.min(
					rectangleTop,
					top
				);
				if (intersectionRight <= intersectionLeft || intersectionTop <= intersectionBottom)
				{
					result = 0;
				}
				else
				{
					if (intersectionLeft == left && intersectionBottom == bottom && intersectionRight == right && intersectionTop == top)
					{
						result = tree.count;
					}
					else
					{
						size = size >> 1;
						result = 0;
						for (int index = 0; index < 4; index++)
						{
							result += count
								(
									rectangleLeft,
									rectangleBottom,
									rectangleRight,
									rectangleTop,
									tree.trees[index],
									quadrantLeft(
										left,
										size,
										index
									),
									quadrantBottom(
										bottom,
										size,
										index
									),
									size
								);
						}
					}
				}
			}
			return result;
		}

		public static int quadrantBottom(
			int bottom,
			int size,
			int index
		)
		{
			return bottom + (index >> 1) * size;
		}

		public static int quadrantLeft(
			int left,
			int size,
			int index
		)
		{
			return left + (index & 1) * size;
		}

		public final Tree2D[] trees;
		public final int count;

		private Tree2D(
			Tree2D[] trees,
			int count
		)
		{
			this.trees = trees;
			this.count = count;
		}

		public Tree2D(Tree2D[] trees)
		{
			this(
				trees,
				count(trees)
			);
		}

		public Tree2D()
		{
			this(TREES_NULL);
		}

		public int count(
			int rectangleLeft,
			int rectangleBottom,
			int rectangleRight,
			int rectangleTop
		)
		{
			return count
				(
					rectangleLeft,
					rectangleBottom,
					rectangleRight,
					rectangleTop,
					this,
					0,
					0,
					SIZE
				);
		}

		public Tree2D setPoint
			(
				int x,
				int y,
				Tree2D tree,
				int left,
				int bottom,
				int size
			)
		{
			Tree2D result;
			if (contains(
				x,
				y,
				left,
				bottom,
				size
			))
			{
				if (size == 1)
				{
					result = new Tree2D(
						TREES_NULL,
						1
					);
				}
				else
				{
					size = size >> 1;
					Tree2D[] trees = new Tree2D[4];
					for (int index = 0; index < 4; index++)
					{
						trees[index] = setPoint
							(
								x,
								y,
								tree == null ? null : tree.trees[index],
								quadrantLeft(
									left,
									size,
									index
								),
								quadrantBottom(
									bottom,
									size,
									index
								),
								size
							);
					}
					result = new Tree2D(trees);
				}
			}
			else
			{
				result = tree;
			}
			return result;
		}

		public Tree2D setPoint(
			int x,
			int y
		)
		{
			return setPoint
				(
					x,
					y,
					this,
					0,
					0,
					SIZE
				);
		}
	}

	public static class Tuple2<Type0, Type1>
	{
		public final Type0 v0;
		public final Type1 v1;

		public Tuple2(
			Type0 v0,
			Type1 v1
		)
		{
			this.v0 = v0;
			this.v1 = v1;
		}

		@Override
		public String toString()
		{
			return "(" + this.v0 + ", " + this.v1 + ")";
		}
	}

	public static class Tuple2Comparable<Type0 extends Comparable<? super Type0>, Type1 extends Comparable<? super Type1>>
		extends Tuple2<Type0, Type1>
		implements Comparable<Tuple2Comparable<Type0, Type1>>
	{
		public Tuple2Comparable(
			Type0 v0,
			Type1 v1
		)
		{
			super(
				v0,
				v1
			);
		}

		@Override
		public int compareTo(Tuple2Comparable<Type0, Type1> that)
		{
			int result = this.v0.compareTo(that.v0);
			if (result == 0)
			{
				result = this.v1.compareTo(that.v1);
			}
			return result;
		}
	}

	public static class Tuple3<Type0, Type1, Type2>
	{
		public final Type0 v0;
		public final Type1 v1;
		public final Type2 v2;

		public Tuple3(
			Type0 v0,
			Type1 v1,
			Type2 v2
		)
		{
			this.v0 = v0;
			this.v1 = v1;
			this.v2 = v2;
		}

		@Override
		public String toString()
		{
			return "(" + this.v0 + ", " + this.v1 + ", " + this.v2 + ")";
		}
	}

	public static class Vertex
		<
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		implements Comparable<Vertex<? super TypeVertex, ? super TypeEdge>>
	{
		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>,
			TypeResult
			> TypeResult breadthFirstSearch
			(
				TypeVertex vertex,
				TypeEdge edge,
				BiFunctionResult<TypeVertex, TypeEdge, TypeResult> function,
				Array<Boolean> visited,
				FIFO<TypeVertex> verticesNext,
				FIFO<TypeEdge> edgesNext,
				TypeResult result
			)
		{
			if (!visited.get(vertex.index))
			{
				visited.set(
					vertex.index,
					true
				);
				result = function.apply(
					vertex,
					edge,
					result
				);
				for (TypeEdge edgeNext : vertex.edges)
				{
					TypeVertex vertexNext = edgeNext.other(vertex);
					if (!visited.get(vertexNext.index))
					{
						verticesNext.push(vertexNext);
						edgesNext.push(edgeNext);
					}
				}
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>,
			TypeResult
			>
		TypeResult breadthFirstSearch
			(
				Array<TypeVertex> vertices,
				int indexVertexStart,
				BiFunctionResult<TypeVertex, TypeEdge, TypeResult> function,
				TypeResult result
			)
		{
			Array<Boolean> visited = new Array<>(
				vertices.size(),
				false
			);
			FIFO<TypeVertex> verticesNext = new FIFO<>();
			verticesNext.push(vertices.get(indexVertexStart));
			FIFO<TypeEdge> edgesNext = new FIFO<>();
			edgesNext.push(null);
			while (!verticesNext.isEmpty())
			{
				result = breadthFirstSearch(
					verticesNext.pop(),
					edgesNext.pop(),
					function,
					visited,
					verticesNext,
					edgesNext,
					result
				);
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		boolean
		cycle
			(
				TypeVertex start,
				SortedSet<TypeVertex> result
			)
		{
			boolean cycle = false;
			Stack<TypeVertex> stackVertex = new Stack<>();
			Stack<TypeEdge> stackEdge = new Stack<>();
			stackVertex.push(start);
			stackEdge.push(null);
			while (!stackVertex.isEmpty())
			{
				TypeVertex vertex = stackVertex.pop();
				TypeEdge edge = stackEdge.pop();
				if (!result.contains(vertex))
				{
					result.add(vertex);
					for (TypeEdge otherEdge : vertex.edges)
					{
						if (otherEdge != edge)
						{
							TypeVertex otherVertex = otherEdge.other(vertex);
							if (result.contains(otherVertex))
							{
								cycle = true;
							}
							else
							{
								stackVertex.push(otherVertex);
								stackEdge.push(otherEdge);
							}
						}
					}
				}
			}
			return cycle;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		SortedSet<TypeVertex>
		depthFirstSearch
			(
				TypeVertex start,
				BiConsumer<TypeVertex, TypeEdge> functionVisitPre,
				BiConsumer<TypeVertex, TypeEdge> functionVisitPost
			)
		{
			SortedSet<TypeVertex> result = new SortedSetAVL<>(Comparator.naturalOrder());
			Stack<TypeVertex> stackVertex = new Stack<>();
			Stack<TypeEdge> stackEdge = new Stack<>();
			stackVertex.push(start);
			stackEdge.push(null);
			while (!stackVertex.isEmpty())
			{
				TypeVertex vertex = stackVertex.pop();
				TypeEdge edge = stackEdge.pop();
				if (result.contains(vertex))
				{
					functionVisitPost.accept(
						vertex,
						edge
					);
				}
				else
				{
					result.add(vertex);
					stackVertex.push(vertex);
					stackEdge.push(edge);
					functionVisitPre.accept(
						vertex,
						edge
					);
					for (TypeEdge otherEdge : vertex.edges)
					{
						TypeVertex otherVertex = otherEdge.other(vertex);
						if (!result.contains(otherVertex))
						{
							stackVertex.push(otherVertex);
							stackEdge.push(otherEdge);
						}
					}
				}
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		SortedSet<TypeVertex>
		depthFirstSearch
			(
				TypeVertex start,
				Consumer<TypeVertex> functionVisitPreVertex,
				Consumer<TypeVertex> functionVisitPostVertex
			)
		{
			BiConsumer<TypeVertex, TypeEdge> functionVisitPreVertexEdge = (vertex, edge) ->
			{
				functionVisitPreVertex.accept(vertex);
			};
			BiConsumer<TypeVertex, TypeEdge> functionVisitPostVertexEdge = (vertex, edge) ->
			{
				functionVisitPostVertex.accept(vertex);
			};
			return depthFirstSearch(
				start,
				functionVisitPreVertexEdge,
				functionVisitPostVertexEdge
			);
		}

		public final int index;
		public final List<TypeEdge> edges;

		public Vertex(int index)
		{
			this.index = index;
			this.edges = new ArrayList<>();
		}

		@Override
		public int compareTo(Vertex<? super TypeVertex, ? super TypeEdge> that)
		{
			return Integer.compare(
				this.index,
				that.index
			);
		}

		@Override
		public String toString()
		{
			return "" + this.index;
		}
	}

	public static class VertexDefault<TypeEdge extends Edge<VertexDefault<TypeEdge>, TypeEdge>>
		extends Vertex<VertexDefault<TypeEdge>, TypeEdge>
	{
		public VertexDefault(int index)
		{
			super(index);
		}
	}

	public static class VertexDefaultDefault
		extends Vertex<VertexDefaultDefault, EdgeDefaultDefault>
	{
		public static Array<VertexDefaultDefault> vertices(int n)
		{
			Array<VertexDefaultDefault> result = new Array<>(n);
			for (int index = 0; index < n; index++)
			{
				result.set(
					index,
					new VertexDefaultDefault(index)
				);
			}
			return result;
		}

		public VertexDefaultDefault(int index)
		{
			super(index);
		}
	}

	public static class Wrapper<Type>
	{
		public Type value;

		public Wrapper(Type value)
		{
			this.value = value;
		}

		public Type get()
		{
			return this.value;
		}

		public void set(Type value)
		{
			this.value = value;
		}

		@Override
		public String toString()
		{
			return this.value.toString();
		}
	}

	public static void add(
		int delta,
		int[] result
	)
	{
		for (int index = 0; index < result.length; index++)
		{
			result[index] += delta;
		}
	}

	public static void add(
		int delta,
		int[]... result
	)
	{
		for (int index = 0; index < result.length; index++)
		{
			add(
				delta,
				result[index]
			);
		}
	}

	public static long add(
		long x,
		long y
	)
	{
		return (x + y) % BIG;
	}

	public static int binarySearchMaximum(
		Function<Integer, Boolean> filter,
		int start,
		int end
	)
	{
		return -binarySearchMinimum(
			x -> filter.apply(-x),
			-end,
			-start
		);
	}

	public static int binarySearchMinimum(
		Function<Integer, Boolean> filter,
		int start,
		int end
	)
	{
		int result;
		if (start == end)
		{
			result = end;
		}
		else
		{
			int middle = start + (end - start) / 2;
			if (filter.apply(middle))
			{
				result = binarySearchMinimum(
					filter,
					start,
					middle
				);
			}
			else
			{
				result = binarySearchMinimum(
					filter,
					middle + 1,
					end
				);
			}
		}
		return result;
	}

	public static void close()
	{
		out.close();
	}

	private static void combinations(
		int n,
		int k,
		int start,
		SortedSet<Integer> combination,
		List<SortedSet<Integer>> result
	)
	{
		if (k == 0)
		{
			result.add(new SortedSetAVL<>(
				combination,
				Comparator.naturalOrder()
			));
		}
		else
		{
			for (int index = start; index < n; index++)
			{
				if (!combination.contains(index))
				{
					combination.add(index);
					combinations(
						n,
						k - 1,
						index + 1,
						combination,
						result
					);
					combination.remove(index);
				}
			}
		}
	}

	public static List<SortedSet<Integer>> combinations(
		int n,
		int k
	)
	{
		List<SortedSet<Integer>> result = new ArrayList<>();
		combinations(
			n,
			k,
			0,
			new SortedSetAVL<>(Comparator.naturalOrder()),
			result
		);
		return result;
	}

	public static <Type> int compare(
		Iterator<Type> iterator0,
		Iterator<Type> iterator1,
		Comparator<Type> comparator
	)
	{
		int result = 0;
		while (result == 0 && iterator0.hasNext() && iterator1.hasNext())
		{
			result = comparator.compare(
				iterator0.next(),
				iterator1.next()
			);
		}
		if (result == 0)
		{
			if (iterator1.hasNext())
			{
				result = -1;
			}
			else
			{
				if (iterator0.hasNext())
				{
					result = 1;
				}
			}
		}
		return result;
	}

	public static <Type> int compare(
		Iterable<Type> iterable0,
		Iterable<Type> iterable1,
		Comparator<Type> comparator
	)
	{
		return compare(
			iterable0.iterator(),
			iterable1.iterator(),
			comparator
		);
	}

	public static long divideCeil(
		long x,
		long y
	)
	{
		return (x + y - 1) / y;
	}

	public static Set<Long> divisors(long n)
	{
		SortedSetAVL<Long> result = new SortedSetAVL<>(Comparator.naturalOrder());
		result.add(1L);
		for (Long factor : factors(n))
		{
			SortedSetAVL<Long> divisors = new SortedSetAVL<>(result);
			for (Long divisor : result)
			{
				divisors.add(divisor * factor);
			}
			result = divisors;
		}
		return result;
	}

	public static LinkedList<Long> factors(long n)
	{
		LinkedList<Long> result = new LinkedList<>();
		Iterator<Long> primes = ITERATOR_BUFFER_PRIME.iterator();
		Long prime;
		while (n > 1 && (prime = primes.next()) * prime <= n)
		{
			while (n % prime == 0)
			{
				result.add(prime);
				n /= prime;
			}
		}
		if (n > 1)
		{
			result.add(n);
		}
		return result;
	}

	public static long faculty(int n)
	{
		long result = 1;
		for (int index = 2; index <= n; index++)
		{
			result *= index;
		}
		return result;
	}

	static long gcd(
		long a,
		long b
	)
	{
		return b == 0 ? a : gcd(
			b,
			a % b
		);
	}

	public static long[] generatePOWER2()
	{
		long[] result = new long[63];
		for (int x = 0; x < result.length; x++)
		{
			result[x] = 1L << x;
		}
		return result;
	}

	public static boolean isPrime(long x)
	{
		boolean result = x > 1;
		Iterator<Long> iterator = ITERATOR_BUFFER_PRIME.iterator();
		Long prime;
		while ((prime = iterator.next()) * prime <= x)
		{
			result &= x % prime > 0;
		}
		return result;
	}

	public static long knapsack(
		List<Tuple3<Long, Integer, Integer>> itemsValueWeightCount,
		int weightMaximum
	)
	{
		long[] valuesMaximum = new long[weightMaximum + 1];
		for (Tuple3<Long, Integer, Integer> itemValueWeightCount : itemsValueWeightCount)
		{
			long itemValue = itemValueWeightCount.v0;
			int itemWeight = itemValueWeightCount.v1;
			int itemCount = itemValueWeightCount.v2;
			for (int weight = weightMaximum; 0 <= weight; weight--)
			{
				for (int index = 1; index <= itemCount && 0 <= weight - index * itemWeight; index++)
				{
					valuesMaximum[weight] = Math.max(
						valuesMaximum[weight],
						valuesMaximum[weight - index * itemWeight] + index * itemValue
					);
				}
			}
		}
		long result = 0;
		for (long valueMaximum : valuesMaximum)
		{
			result = Math.max(
				result,
				valueMaximum
			);
		}
		return result;
	}

	public static boolean knapsackPossible(
		List<Tuple2<Integer, Integer>> itemsWeightCount,
		int weightMaximum
	)
	{
		boolean[] weightPossible = new boolean[weightMaximum + 1];
		weightPossible[0] = true;
		int weightLargest = 0;
		for (Tuple2<Integer, Integer> itemWeightCount : itemsWeightCount)
		{
			int itemWeight = itemWeightCount.v0;
			int itemCount = itemWeightCount.v1;
			for (int weightStart = 0; weightStart < itemWeight; weightStart++)
			{
				int count = 0;
				for (int weight = weightStart; weight <= weightMaximum && (0 < count || weight <= weightLargest); weight += itemWeight)
				{
					if (weightPossible[weight])
					{
						count = itemCount;
					}
					else
					{
						if (0 < count)
						{
							weightPossible[weight] = true;
							weightLargest = weight;
							count -= 1;
						}
					}
				}
			}
		}
		return weightPossible[weightMaximum];
	}

	public static long lcm(
		int a,
		int b
	)
	{
		return a * b / gcd(
			a,
			b
		);
	}

	public static void main(String[] args)
	{
		try
		{
			solve();
		}
		catch (IOException exception)
		{
			exception.printStackTrace();
		}
		close();
	}

	public static long mul(
		long x,
		long y
	)
	{
		return (x * y) % BIG;
	}

	public static double nextDouble()
		throws IOException
	{
		return Double.parseDouble(nextString());
	}

	public static int nextInt()
		throws IOException
	{
		return Integer.parseInt(nextString());
	}

	public static void nextInts(
		int n,
		int[]... result
	)
		throws IOException
	{
		for (int index = 0; index < n; index++)
		{
			for (int value = 0; value < result.length; value++)
			{
				result[value][index] = nextInt();
			}
		}
	}

	public static int[] nextInts(int n)
		throws IOException
	{
		int[] result = new int[n];
		nextInts(
			n,
			result
		);
		return result;
	}

	public static String nextLine()
		throws IOException
	{
		return bufferedReader.readLine();
	}

	public static long nextLong()
		throws IOException
	{
		return Long.parseLong(nextString());
	}

	public static void nextLongs(
		int n,
		long[]... result
	)
		throws IOException
	{
		for (int index = 0; index < n; index++)
		{
			for (int value = 0; value < result.length; value++)
			{
				result[value][index] = nextLong();
			}
		}
	}

	public static long[] nextLongs(int n)
		throws IOException
	{
		long[] result = new long[n];
		nextLongs(
			n,
			result
		);
		return result;
	}

	public static String nextString()
		throws IOException
	{
		while ((stringTokenizer == null) || (!stringTokenizer.hasMoreTokens()))
		{
			stringTokenizer = new StringTokenizer(bufferedReader.readLine());
		}
		return stringTokenizer.nextToken();
	}

	public static String[] nextStrings(int n)
		throws IOException
	{
		String[] result = new String[n];
		{
			for (int index = 0; index < n; index++)
			{
				result[index] = nextString();
			}
		}
		return result;
	}

	public static <T> List<T> permutation(
		long p,
		List<T> x
	)
	{
		List<T> copy = new ArrayList<>();
		for (int index = 0; index < x.size(); index++)
		{
			copy.add(x.get(index));
		}
		List<T> result = new ArrayList<>();
		for (int indexTo = 0; indexTo < x.size(); indexTo++)
		{
			int indexFrom = (int) p % copy.size();
			p = p / copy.size();
			result.add(copy.remove(indexFrom));
		}
		return result;
	}

	public static <Type> List<List<Type>> permutations(List<Type> list)
	{
		List<List<Type>> result = new ArrayList<>();
		result.add(new ArrayList<>());
		for (Type element : list)
		{
			List<List<Type>> permutations = result;
			result = new ArrayList<>();
			for (List<Type> permutation : permutations)
			{
				for (int index = 0; index <= permutation.size(); index++)
				{
					List<Type> permutationNew = new ArrayList<>(permutation);
					permutationNew.add(
						index,
						element
					);
					result.add(permutationNew);
				}
			}
		}
		return result;
	}

	public static long[][] sizeGroup2CombinationsCount(int maximum)
	{
		long[][] result = new long[maximum + 1][maximum + 1];
		for (int length = 0; length <= maximum; length++)
		{
			result[length][0] = 1;
			for (int group = 1; group <= length; group++)
			{
				result[length][group] = add(
					result[length - 1][group - 1],
					result[length - 1][group]
				);
			}
		}
		return result;
	}

	public static Stream<BigInteger> streamFibonacci()
	{
		return Stream.generate(new Supplier<BigInteger>()
		{
			private BigInteger n0 = BigInteger.ZERO;
			private BigInteger n1 = BigInteger.ONE;

			@Override
			public BigInteger get()
			{
				BigInteger result = n0;
				n0 = n1;
				n1 = result.add(n0);
				return result;
			}
		});
	}

	public static Stream<Long> streamPrime(int sieveSize)
	{
		return Stream.generate(new Supplier<Long>()
		{
			private boolean[] isPrime = new boolean[sieveSize];
			private long sieveOffset = 2;
			private List<Long> primes = new ArrayList<>();
			private int index = 0;

			public void filter(
				long prime,
				boolean[] result
			)
			{
				if (prime * prime < this.sieveOffset + sieveSize)
				{
					long remainingStart = this.sieveOffset % prime;
					long start = remainingStart == 0 ? 0 : prime - remainingStart;
					for (long index = start; index < sieveSize; index += prime)
					{
						result[(int) index] = false;
					}
				}
			}

			public void generatePrimes()
			{
				Arrays.fill(
					this.isPrime,
					true
				);
				this.primes.forEach(prime -> filter(
					prime,
					isPrime
				));
				for (int index = 0; index < sieveSize; index++)
				{
					if (isPrime[index])
					{
						this.primes.add(this.sieveOffset + index);
						filter(
							this.sieveOffset + index,
							isPrime
						);
					}
				}
				this.sieveOffset += sieveSize;
			}

			@Override
			public Long get()
			{
				while (this.primes.size() <= this.index)
				{
					generatePrimes();
				}
				Long result = this.primes.get(this.index);
				this.index += 1;
				return result;
			}
		});
	}

	public static <Type> String toString(
		Iterator<Type> iterator,
		String separator
	)
	{
		StringBuilder stringBuilder = new StringBuilder();
		if (iterator.hasNext())
		{
			stringBuilder.append(iterator.next());
		}
		while (iterator.hasNext())
		{
			stringBuilder.append(separator);
			stringBuilder.append(iterator.next());
		}
		return stringBuilder.toString();
	}

	public static <Type> String toString(Iterator<Type> iterator)
	{
		return toString(
			iterator,
			" "
		);
	}

	public static <Type> String toString(
		Iterable<Type> iterable,
		String separator
	)
	{
		return toString(
			iterable.iterator(),
			separator
		);
	}

	public static <Type> String toString(Iterable<Type> iterable)
	{
		return toString(
			iterable,
			" "
		);
	}

	public static long totient(long n)
	{
		Set<Long> factors = new SortedSetAVL<>(
			factors(n),
			Comparator.naturalOrder()
		);
		long result = n;
		for (long p : factors)
		{
			result -= result / p;
		}
		return result;
	}

	interface BiFunctionResult<Type0, Type1, TypeResult>
	{
		TypeResult apply(
			Type0 x0,
			Type1 x1,
			TypeResult x2
		);
	}

	static class Point
		implements Comparable<Point>
	{
		public final int x;
		public final int y;

		@Override
		public int compareTo(Point that)
		{
			int result = Integer.compare(
				this.x,
				that.x
			);
			if (result == 0)
			{
				result = Integer.compare(
					this.y,
					that.y
				);
			}
			return result;
		}

		public Point(
			int x,
			int y
		)
		{
			this.x = x;
			this.y = y;
		}

		public int level()
		{
			return Math.max(
				this.x,
				this.y
			);
		}

		public long distance(Point point)
		{
			return Math.abs(this.x - point.x) + Math.abs(this.y - point.y);
		}

		public String toString()
		{
			return "(" + this.x + ", " + this.y + ")";
		}
	}

	public static Point min
		(
			Set<Point> points,
			Function<Point, Integer> function1,
			Function<Point, Integer> function2
		)
	{
		Iterator<Point> iterator = points.iterator();
		Point result = iterator.next();
		while (iterator.hasNext())
		{
			Point point = iterator.next();
			if (function1.apply(point) < function1.apply(result))
			{
				result = point;
			}
			else
			{
				if (function1.apply(point) == function1.apply(result) && function2.apply(point) < function2.apply(result))
				{
					result = point;
				}
			}
		}
		return result;
	}

	public static long solve(Point[] pointsArray)
	{
		MapSet<Integer, Point> level2Points = new MapSet<>(
			Comparator.naturalOrder(),
			Comparator.naturalOrder()
		);
		for (int index = 0; index < pointsArray.length; index++)
		{
			level2Points.add(
				pointsArray[index].level(),
				pointsArray[index]
			);
		}
		long resultLeft = 0;
		long resultDown = 0;
		Point lastLeft = new Point(
			0,
			0
		);
		Point lastDown = new Point(
			0,
			0
		);
		for (Map.Entry<Integer, SortedSetAVL<Point>> entry : level2Points.entrySet)
		{
			Set<Point> points = entry.getValue();
			Point left = min
				(
					points,
					point -> point.x,
					point -> -point.y
				);
			Point down = min
				(
					points,
					point -> point.y,
					point -> -point.x
				);
			long distanceLevel = down.distance(left);
			long resultLeftNew = Math.min
				(
					resultLeft + lastLeft.distance(down),
					resultDown + lastDown.distance(down)
				) + distanceLevel;
			long resultDownNew = Math.min
				(
					resultLeft + lastLeft.distance(left),
					resultDown + lastDown.distance(left)
				) + distanceLevel;
			resultLeft = resultLeftNew;
			resultDown = resultDownNew;
			lastLeft = left;
			lastDown = down;
		}
		return Math.min(
			resultDown,
			resultLeft
		);
	}

	public static void solve()
		throws IOException
	{
		int n = nextInt();
		Point[] points = new Point[n];
		for (int index = 0; index < n; index++)
		{
			Point point = new Point(
				nextInt(),
				nextInt()
			);
			points[index] = point;
		}
		out.println(solve(points));
	}
}

import java.io.*;
import java.math.BigInteger;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class F_515
{
	public static final long[] POWER2 = generatePOWER2();
	public static final IteratorBuffer<Long> ITERATOR_BUFFER_PRIME = new IteratorBuffer<>(streamPrime(1000000).iterator());
	public static long BIG = 1000000000 + 7;
	private static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
	private static StringTokenizer stringTokenizer = null;
	private static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

	static class Array<Type>
		implements Iterable<Type>
	{
		private final Object[] array;

		public Array(int size)
		{
			this.array = new Object[size];
		}

		public Array(
			int size,
			Type element
		)
		{
			this(size);
			Arrays.fill(
				this.array,
				element
			);
		}

		public Array(
			Array<Type> array,
			Type element
		)
		{
			this(array.size() + 1);
			for (int index = 0; index < array.size(); index++)
			{
				set(
					index,
					array.get(index)
				);
			}
			set(
				size() - 1,
				element
			);
		}

		public Array(List<Type> list)
		{
			this(list.size());
			int index = 0;
			for (Type element : list)
			{
				set(
					index,
					element
				);
				index += 1;
			}
		}

		public Type get(int index)
		{
			return (Type) this.array[index];
		}

		@Override
		public Iterator<Type> iterator()
		{
			return new Iterator<Type>()
			{
				int index = 0;

				@Override
				public boolean hasNext()
				{
					return this.index < size();
				}

				@Override
				public Type next()
				{
					Type result = Array.this.get(index);
					index += 1;
					return result;
				}
			};
		}

		public Array set(
			int index,
			Type value
		)
		{
			this.array[index] = value;
			return this;
		}

		public int size()
		{
			return this.array.length;
		}

		public List<Type> toList()
		{
			List<Type> result = new ArrayList<>();
			for (Type element : this)
			{
				result.add(element);
			}
			return result;
		}

		@Override
		public String toString()
		{
			return "[" + F_515.toString(
				this,
				", "
			) + "]";
		}
	}

	static class BIT
	{
		private static int lastBit(int index)
		{
			return index & -index;
		}

		private final long[] tree;

		public BIT(int size)
		{
			this.tree = new long[size];
		}

		public void add(
			int index,
			long delta
		)
		{
			index += 1;
			while (index <= this.tree.length)
			{
				tree[index - 1] += delta;
				index += lastBit(index);
			}
		}

		public long prefix(int end)
		{
			long result = 0;
			while (end > 0)
			{
				result += this.tree[end - 1];
				end -= lastBit(end);
			}
			return result;
		}

		public int size()
		{
			return this.tree.length;
		}

		public long sum(
			int start,
			int end
		)
		{
			return prefix(end) - prefix(start);
		}
	}

	static abstract class Edge<TypeVertex extends Vertex<TypeVertex, TypeEdge>, TypeEdge extends Edge<TypeVertex, TypeEdge>>
	{
		public final TypeVertex vertex0;
		public final TypeVertex vertex1;
		public final boolean bidirectional;

		public Edge(
			TypeVertex vertex0,
			TypeVertex vertex1,
			boolean bidirectional
		)
		{
			this.vertex0 = vertex0;
			this.vertex1 = vertex1;
			this.bidirectional = bidirectional;
			this.vertex0.edges.add(getThis());
			if (this.bidirectional)
			{
				this.vertex1.edges.add(getThis());
			}
		}

		public abstract TypeEdge getThis();

		public TypeVertex other(Vertex<TypeVertex, TypeEdge> vertex)
		{
			TypeVertex result;
			if (vertex0 == vertex)
			{
				result = vertex1;
			}
			else
			{
				result = vertex0;
			}
			return result;
		}

		public void remove()
		{
			this.vertex0.edges.remove(getThis());
			if (this.bidirectional)
			{
				this.vertex1.edges.remove(getThis());
			}
		}

		@Override
		public String toString()
		{
			return this.vertex0 + "->" + this.vertex1;
		}
	}

	public static class EdgeDefault<TypeVertex extends Vertex<TypeVertex, EdgeDefault<TypeVertex>>>
		extends Edge<TypeVertex, EdgeDefault<TypeVertex>>
	{
		public EdgeDefault(
			TypeVertex vertex0,
			TypeVertex vertex1,
			boolean bidirectional
		)
		{
			super(
				vertex0,
				vertex1,
				bidirectional
			);
		}

		@Override
		public EdgeDefault<TypeVertex> getThis()
		{
			return this;
		}
	}

	public static class EdgeDefaultDefault
		extends Edge<VertexDefaultDefault, EdgeDefaultDefault>
	{
		public EdgeDefaultDefault(
			VertexDefaultDefault vertex0,
			VertexDefaultDefault vertex1,
			boolean bidirectional
		)
		{
			super(
				vertex0,
				vertex1,
				bidirectional
			);
		}

		@Override
		public EdgeDefaultDefault getThis()
		{
			return this;
		}
	}

	public static class FIFO<Type>
	{
		public SingleLinkedList<Type> start;
		public SingleLinkedList<Type> end;

		public FIFO()
		{
			this.start = null;
			this.end = null;
		}

		public boolean isEmpty()
		{
			return this.start == null;
		}

		public Type peek()
		{
			return this.start.element;
		}

		public Type pop()
		{
			Type result = this.start.element;
			this.start = this.start.next;
			return result;
		}

		public void push(Type element)
		{
			SingleLinkedList<Type> list = new SingleLinkedList<>(
				element,
				null
			);
			if (this.start == null)
			{
				this.start = list;
				this.end = list;
			}
			else
			{
				this.end.next = list;
				this.end = list;
			}
		}
	}

	static class Fraction
		implements Comparable<Fraction>
	{
		public static final Fraction ZERO = new Fraction(
			0,
			1
		);

		public static Fraction fraction(long whole)
		{
			return fraction(
				whole,
				1
			);
		}

		public static Fraction fraction(
			long numerator,
			long denominator
		)
		{
			Fraction result;
			if (denominator == 0)
			{
				throw new ArithmeticException();
			}
			if (numerator == 0)
			{
				result = Fraction.ZERO;
			}
			else
			{
				int sign;
				if (numerator < 0 ^ denominator < 0)
				{
					sign = -1;
					numerator = Math.abs(numerator);
					denominator = Math.abs(denominator);
				}
				else
				{
					sign = 1;
				}
				long gcd = gcd(
					numerator,
					denominator
				);
				result = new Fraction(
					sign * numerator / gcd,
					denominator / gcd
				);
			}
			return result;
		}

		public final long numerator;
		public final long denominator;

		private Fraction(
			long numerator,
			long denominator
		)
		{
			this.numerator = numerator;
			this.denominator = denominator;
		}

		public Fraction add(Fraction fraction)
		{
			return fraction(
				this.numerator * fraction.denominator + fraction.numerator * this.denominator,
				this.denominator * fraction.denominator
			);
		}

		@Override
		public int compareTo(Fraction that)
		{
			return Long.compare(
				this.numerator * that.denominator,
				that.numerator * this.denominator
			);
		}

		public Fraction divide(Fraction fraction)
		{
			return multiply(fraction.inverse());
		}

		public boolean equals(Fraction that)
		{
			return this.compareTo(that) == 0;
		}

		public boolean equals(Object that)
		{
			return this.compareTo((Fraction) that) == 0;
		}

		public Fraction getRemainder()
		{
			return fraction(
				this.numerator - getWholePart() * denominator,
				denominator
			);
		}

		public long getWholePart()
		{
			return this.numerator / this.denominator;
		}

		public Fraction inverse()
		{
			return fraction(
				this.denominator,
				this.numerator
			);
		}

		public Fraction multiply(Fraction fraction)
		{
			return fraction(
				this.numerator * fraction.numerator,
				this.denominator * fraction.denominator
			);
		}

		public Fraction neg()
		{
			return fraction(
				-this.numerator,
				this.denominator
			);
		}

		public Fraction sub(Fraction fraction)
		{
			return add(fraction.neg());
		}

		@Override
		public String toString()
		{
			String result;
			if (getRemainder().equals(Fraction.ZERO))
			{
				result = "" + this.numerator;
			}
			else
			{
				result = this.numerator + "/" + this.denominator;
			}
			return result;
		}
	}

	static class IteratorBuffer<Type>
	{
		private Iterator<Type> iterator;
		private List<Type> list;

		public IteratorBuffer(Iterator<Type> iterator)
		{
			this.iterator = iterator;
			this.list = new ArrayList<Type>();
		}

		public Iterator<Type> iterator()
		{
			return new Iterator<Type>()
			{
				int index = 0;

				@Override
				public boolean hasNext()
				{
					return this.index < list.size() || IteratorBuffer.this.iterator.hasNext();
				}

				@Override
				public Type next()
				{
					if (list.size() <= this.index)
					{
						list.add(iterator.next());
					}
					Type result = list.get(index);
					index += 1;
					return result;
				}
			};
		}
	}

	public static class MapCount<Type>
		extends SortedMapAVL<Type, Long>
	{
		private int count;

		public MapCount(Comparator<? super Type> comparator)
		{
			super(comparator);
			this.count = 0;
		}

		public long add(
			Type key,
			Long delta
		)
		{
			long result;
			if (delta > 0)
			{
				Long value = get(key);
				if (value == null)
				{
					value = delta;
				}
				else
				{
					value += delta;
				}
				put(
					key,
					value
				);
				result = delta;
			}
			else
			{
				result = 0;
			}
			this.count += result;
			return result;
		}

		public int count()
		{
			return this.count;
		}

		public List<Type> flatten()
		{
			List<Type> result = new ArrayList<>();
			for (Entry<Type, Long> entry : entrySet())
			{
				for (long index = 0; index < entry.getValue(); index++)
				{
					result.add(entry.getKey());
				}
			}
			return result;
		}

		@Override
		public SortedMapAVL<Type, Long> headMap(Type keyEnd)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public void putAll(Map<? extends Type, ? extends Long> map)
		{
			throw new UnsupportedOperationException();
		}

		public long remove(
			Type key,
			Long delta
		)
		{
			long result;
			if (delta > 0)
			{
				Long value = get(key) - delta;
				if (value <= 0)
				{
					result = delta + value;
					remove(key);
				}
				else
				{
					result = delta;
					put(
						key,
						value
					);
				}
			}
			else
			{
				result = 0;
			}
			this.count -= result;
			return result;
		}

		@Override
		public Long remove(Object key)
		{
			Long result = super.remove(key);
			this.count -= result;
			return result;
		}

		@Override
		public SortedMapAVL<Type, Long> subMap(
			Type keyStart,
			Type keyEnd
		)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public SortedMapAVL<Type, Long> tailMap(Type keyStart)
		{
			throw new UnsupportedOperationException();
		}
	}

	public static class MapSet<TypeKey, TypeValue>
		extends SortedMapAVL<TypeKey, SortedSetAVL<TypeValue>>
		implements Iterable<TypeValue>
	{
		private Comparator<? super TypeValue> comparatorValue;

		public MapSet(
			Comparator<? super TypeKey> comparatorKey,
			Comparator<? super TypeValue> comparatorValue
		)
		{
			super(comparatorKey);
			this.comparatorValue = comparatorValue;
		}

		public MapSet(
			Comparator<? super TypeKey> comparatorKey,
			SortedSetAVL<Entry<TypeKey, SortedSetAVL<TypeValue>>> entrySet,
			Comparator<? super TypeValue> comparatorValue
		)
		{
			super(
				comparatorKey,
				entrySet
			);
			this.comparatorValue = comparatorValue;
		}

		public boolean add(
			TypeKey key,
			TypeValue value
		)
		{
			SortedSetAVL<TypeValue> set = computeIfAbsent(
				key,
				k -> new SortedSetAVL<>(comparatorValue)
			);
			return set.add(value);
		}

		public TypeValue firstValue()
		{
			TypeValue result;
			Entry<TypeKey, SortedSetAVL<TypeValue>> firstEntry = firstEntry();
			if (firstEntry == null)
			{
				result = null;
			}
			else
			{
				result = firstEntry.getValue().first();
			}
			return result;
		}

		@Override
		public MapSet<TypeKey, TypeValue> headMap(TypeKey keyEnd)
		{
			return new MapSet<>(
				this.comparator,
				this.entrySet.headSet(new AbstractMap.SimpleEntry<>(
					keyEnd,
					null
				)),
				this.comparatorValue
			);
		}

		public Iterator<TypeValue> iterator()
		{
			return new Iterator<TypeValue>()
			{
				Iterator<SortedSetAVL<TypeValue>> iteratorValues = values().iterator();
				Iterator<TypeValue> iteratorValue = null;

				@Override
				public boolean hasNext()
				{
					return iteratorValues.hasNext() || (iteratorValue != null && iteratorValue.hasNext());
				}

				@Override
				public TypeValue next()
				{
					if (iteratorValue == null || !iteratorValue.hasNext())
					{
						iteratorValue = iteratorValues.next().iterator();
					}
					return iteratorValue.next();
				}
			};
		}

		public TypeValue lastValue()
		{
			TypeValue result;
			Entry<TypeKey, SortedSetAVL<TypeValue>> lastEntry = lastEntry();
			if (lastEntry == null)
			{
				result = null;
			}
			else
			{
				result = lastEntry.getValue().last();
			}
			return result;
		}

		public boolean removeSet(
			TypeKey key,
			TypeValue value
		)
		{
			boolean result;
			SortedSetAVL<TypeValue> set = get(key);
			if (set == null)
			{
				result = false;
			}
			else
			{
				result = set.remove(value);
				if (set.size() == 0)
				{
					remove(key);
				}
			}
			return result;
		}

		@Override
		public MapSet<TypeKey, TypeValue> tailMap(TypeKey keyStart)
		{
			return new MapSet<>(
				this.comparator,
				this.entrySet.tailSet(new AbstractMap.SimpleEntry<>(
					keyStart,
					null
				)),
				this.comparatorValue
			);
		}
	}

	public static class Matrix
	{
		public final int rows;
		public final int columns;
		public final Fraction[][] cells;

		public Matrix(
			int rows,
			int columns
		)
		{
			this.rows = rows;
			this.columns = columns;
			this.cells = new Fraction[rows][columns];
			for (int row = 0; row < rows; row++)
			{
				for (int column = 0; column < columns; column++)
				{
					set(
						row,
						column,
						Fraction.ZERO
					);
				}
			}
		}

		public void add(
			int rowSource,
			int rowTarget,
			Fraction fraction
		)
		{
			for (int column = 0; column < columns; column++)
			{
				this.cells[rowTarget][column] = this.cells[rowTarget][column].add(this.cells[rowSource][column].multiply(fraction));
			}
		}

		private int columnPivot(int row)
		{
			int result = this.columns;
			for (int column = this.columns - 1; 0 <= column; column--)
			{
				if (this.cells[row][column].compareTo(Fraction.ZERO) != 0)
				{
					result = column;
				}
			}
			return result;
		}

		public void reduce()
		{
			for (int rowMinimum = 0; rowMinimum < this.rows; rowMinimum++)
			{
				int rowPivot = rowPivot(rowMinimum);
				if (rowPivot != -1)
				{
					int columnPivot = columnPivot(rowPivot);
					Fraction current = this.cells[rowMinimum][columnPivot];
					Fraction pivot = this.cells[rowPivot][columnPivot];
					Fraction fraction = pivot.inverse().sub(current.divide(pivot));
					add(
						rowPivot,
						rowMinimum,
						fraction
					);
					for (int row = rowMinimum + 1; row < this.rows; row++)
					{
						if (columnPivot(row) == columnPivot)
						{
							add(
								rowMinimum,
								row,
								this.cells[row][columnPivot(row)].neg()
							);
						}
					}
				}
			}
		}

		private int rowPivot(int rowMinimum)
		{
			int result = -1;
			int pivotColumnMinimum = this.columns;
			for (int row = rowMinimum; row < this.rows; row++)
			{
				int pivotColumn = columnPivot(row);
				if (pivotColumn < pivotColumnMinimum)
				{
					result = row;
					pivotColumnMinimum = pivotColumn;
				}
			}
			return result;
		}

		public void set(
			int row,
			int column,
			Fraction value
		)
		{
			this.cells[row][column] = value;
		}

		public String toString()
		{
			String result = "";
			for (int row = 0; row < rows; row++)
			{
				for (int column = 0; column < columns; column++)
				{
					result += this.cells[row][column] + "\t";
				}
				result += "\n";
			}
			return result;
		}
	}

	public static class Node<Type>
	{
		public static <Type> Node<Type> balance(Node<Type> result)
		{
			while (result != null && 1 < Math.abs(height(result.left) - height(result.right)))
			{
				if (height(result.left) < height(result.right))
				{
					Node<Type> right = result.right;
					if (height(right.right) < height(right.left))
					{
						result = new Node<>(
							result.value,
							result.left,
							right.rotateRight()
						);
					}
					result = result.rotateLeft();
				}
				else
				{
					Node<Type> left = result.left;
					if (height(left.left) < height(left.right))
					{
						result = new Node<>(
							result.value,
							left.rotateLeft(),
							result.right
						);
					}
					result = result.rotateRight();
				}
			}
			return result;
		}

		public static <Type> Node<Type> clone(Node<Type> result)
		{
			if (result != null)
			{
				result = new Node<>(
					result.value,
					clone(result.left),
					clone(result.right)
				);
			}
			return result;
		}

		public static <Type> Node<Type> delete(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					if (node.left == null)
					{
						result = node.right;
					}
					else
					{
						if (node.right == null)
						{
							result = node.left;
						}
						else
						{
							Node<Type> first = first(node.right);
							result = new Node<>(
								first.value,
								node.left,
								delete(
									node.right,
									first.value,
									comparator
								)
							);
						}
					}
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							delete(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							delete(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> Node<Type> first(Node<Type> result)
		{
			while (result.left != null)
			{
				result = result.left;
			}
			return result;
		}

		public static <Type> Node<Type> get(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = node;
				}
				else
				{
					if (compare < 0)
					{
						result = get(
							node.left,
							value,
							comparator
						);
					}
					else
					{
						result = get(
							node.right,
							value,
							comparator
						);
					}
				}
			}
			return result;
		}

		public static <Type> Node<Type> head(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = node.left;
				}
				else
				{
					if (compare < 0)
					{
						result = head(
							node.left,
							value,
							comparator
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							head(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static int height(Node node)
		{
			return node == null ? 0 : node.height;
		}

		public static <Type> Node<Type> insert(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = new Node<>(
					value,
					null,
					null
				);
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = new Node<>(
						value,
						node.left,
						node.right
					);
					;
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							insert(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = new Node<>(
							node.value,
							node.left,
							insert(
								node.right,
								value,
								comparator
							)
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> Node<Type> last(Node<Type> result)
		{
			while (result.right != null)
			{
				result = result.right;
			}
			return result;
		}

		public static int size(Node node)
		{
			return node == null ? 0 : node.size;
		}

		public static <Type> Node<Type> tail(
			Node<Type> node,
			Type value,
			Comparator<? super Type> comparator
		)
		{
			Node<Type> result;
			if (node == null)
			{
				result = null;
			}
			else
			{
				int compare = comparator.compare(
					value,
					node.value
				);
				if (compare == 0)
				{
					result = new Node<>(
						node.value,
						null,
						node.right
					);
				}
				else
				{
					if (compare < 0)
					{
						result = new Node<>(
							node.value,
							tail(
								node.left,
								value,
								comparator
							),
							node.right
						);
					}
					else
					{
						result = tail(
							node.right,
							value,
							comparator
						);
					}
				}
				result = balance(result);
			}
			return result;
		}

		public static <Type> void traverseOrderIn(
			Node<Type> node,
			Consumer<Type> consumer
		)
		{
			if (node != null)
			{
				traverseOrderIn(
					node.left,
					consumer
				);
				consumer.accept(node.value);
				traverseOrderIn(
					node.right,
					consumer
				);
			}
		}

		public final Type value;
		public final Node<Type> left;
		public final Node<Type> right;
		public final int size;
		private final int height;

		public Node(
			Type value,
			Node<Type> left,
			Node<Type> right
		)
		{
			this.value = value;
			this.left = left;
			this.right = right;
			this.size = 1 + size(left) + size(right);
			this.height = 1 + Math.max(
				height(left),
				height(right)
			);
		}

		public Node<Type> rotateLeft()
		{
			Node<Type> left = new Node<>(
				this.value,
				this.left,
				this.right.left
			);
			return new Node<>(
				this.right.value,
				left,
				this.right.right
			);
		}

		public Node<Type> rotateRight()
		{
			Node<Type> right = new Node<>(
				this.value,
				this.left.right,
				this.right
			);
			return new Node<>(
				this.left.value,
				this.left.left,
				right
			);
		}
	}

	public static class SingleLinkedList<Type>
	{
		public final Type element;
		public SingleLinkedList<Type> next;

		public SingleLinkedList(
			Type element,
			SingleLinkedList<Type> next
		)
		{
			this.element = element;
			this.next = next;
		}

		public void toCollection(Collection<Type> collection)
		{
			if (this.next != null)
			{
				this.next.toCollection(collection);
			}
			collection.add(this.element);
		}
	}

	public static class SmallSetIntegers
	{
		public static final int SIZE = 20;
		public static final int[] SET = generateSet();
		public static final int[] COUNT = generateCount();
		public static final int[] INTEGER = generateInteger();

		private static int count(int set)
		{
			int result = 0;
			for (int integer = 0; integer < SIZE; integer++)
			{
				if (0 < (set & set(integer)))
				{
					result += 1;
				}
			}
			return result;
		}

		private static final int[] generateCount()
		{
			int[] result = new int[1 << SIZE];
			for (int set = 0; set < result.length; set++)
			{
				result[set] = count(set);
			}
			return result;
		}

		private static final int[] generateInteger()
		{
			int[] result = new int[1 << SIZE];
			Arrays.fill(
				result,
				-1
			);
			for (int integer = 0; integer < SIZE; integer++)
			{
				result[SET[integer]] = integer;
			}
			return result;
		}

		private static final int[] generateSet()
		{
			int[] result = new int[SIZE];
			for (int integer = 0; integer < result.length; integer++)
			{
				result[integer] = set(integer);
			}
			return result;
		}

		private static int set(int integer)
		{
			return 1 << integer;
		}
	}

	public static class SortedMapAVL<TypeKey, TypeValue>
		implements SortedMap<TypeKey, TypeValue>
	{
		public final Comparator<? super TypeKey> comparator;
		public final SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet;

		public SortedMapAVL(Comparator<? super TypeKey> comparator)
		{
			this(
				comparator,
				new SortedSetAVL<>((entry0, entry1) -> comparator.compare(
					entry0.getKey(),
					entry1.getKey()
				))
			);
		}

		private SortedMapAVL(
			Comparator<? super TypeKey> comparator,
			SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet
		)
		{
			this.comparator = comparator;
			this.entrySet = entrySet;
		}

		@Override
		public void clear()
		{
			this.entrySet.clear();
		}

		@Override
		public Comparator<? super TypeKey> comparator()
		{
			return this.comparator;
		}

		@Override
		public boolean containsKey(Object key)
		{
			return this.entrySet().contains(new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			));
		}

		@Override
		public boolean containsValue(Object value)
		{
			throw new UnsupportedOperationException();
		}

		@Override
		public SortedSetAVL<Entry<TypeKey, TypeValue>> entrySet()
		{
			return this.entrySet;
		}

		public Entry<TypeKey, TypeValue> firstEntry()
		{
			return this.entrySet.first();
		}

		@Override
		public TypeKey firstKey()
		{
			return firstEntry().getKey();
		}

		@Override
		public TypeValue get(Object key)
		{
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			);
			entry = this.entrySet.get(entry);
			return entry == null ? null : entry.getValue();
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> headMap(TypeKey keyEnd)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.headSet(new AbstractMap.SimpleEntry<>(
					keyEnd,
					null
				))
			);
		}

		@Override
		public boolean isEmpty()
		{
			return this.entrySet.isEmpty();
		}

		@Override
		public Set<TypeKey> keySet()
		{
			return new SortedSet<TypeKey>()
			{
				@Override
				public boolean add(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean addAll(Collection<? extends TypeKey> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public void clear()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public Comparator<? super TypeKey> comparator()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean contains(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean containsAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public TypeKey first()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public SortedSet<TypeKey> headSet(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean isEmpty()
				{
					return size() == 0;
				}

				@Override
				public Iterator<TypeKey> iterator()
				{
					final Iterator<Entry<TypeKey, TypeValue>> iterator = SortedMapAVL.this.entrySet.iterator();
					return new Iterator<TypeKey>()
					{
						@Override
						public boolean hasNext()
						{
							return iterator.hasNext();
						}

						@Override
						public TypeKey next()
						{
							return iterator.next().getKey();
						}
					};
				}

				@Override
				public TypeKey last()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean remove(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean removeAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean retainAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public int size()
				{
					return SortedMapAVL.this.entrySet.size();
				}

				@Override
				public SortedSet<TypeKey> subSet(
					TypeKey typeKey,
					TypeKey e1
				)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public SortedSet<TypeKey> tailSet(TypeKey typeKey)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public Object[] toArray()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public <T> T[] toArray(T[] ts)
				{
					throw new UnsupportedOperationException();
				}
			};
		}

		public Entry<TypeKey, TypeValue> lastEntry()
		{
			return this.entrySet.last();
		}

		@Override
		public TypeKey lastKey()
		{
			return lastEntry().getKey();
		}

		@Override
		public TypeValue put(
			TypeKey key,
			TypeValue value
		)
		{
			TypeValue result = get(key);
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				key,
				value
			);
			this.entrySet().add(entry);
			return result;
		}

		@Override
		public void putAll(Map<? extends TypeKey, ? extends TypeValue> map)
		{
			map.entrySet()
				.forEach(entry -> put(
					entry.getKey(),
					entry.getValue()
				));
		}

		@Override
		public TypeValue remove(Object key)
		{
			TypeValue result = get(key);
			Entry<TypeKey, TypeValue> entry = new AbstractMap.SimpleEntry<>(
				(TypeKey) key,
				null
			);
			this.entrySet.remove(entry);
			return result;
		}

		@Override
		public int size()
		{
			return this.entrySet().size();
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> subMap(
			TypeKey keyStart,
			TypeKey keyEnd
		)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.subSet(
					new AbstractMap.SimpleEntry<>(
						keyStart,
						null
					),
					new AbstractMap.SimpleEntry<>(
						keyEnd,
						null
					)
				)
			);
		}

		@Override
		public SortedMapAVL<TypeKey, TypeValue> tailMap(TypeKey keyStart)
		{
			return new SortedMapAVL<>(
				this.comparator,
				this.entrySet.tailSet(new AbstractMap.SimpleEntry<>(
					keyStart,
					null
				))
			);
		}

		@Override
		public String toString()
		{
			return this.entrySet().toString();
		}

		@Override
		public Collection<TypeValue> values()
		{
			return new Collection<TypeValue>()
			{
				@Override
				public boolean add(TypeValue typeValue)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean addAll(Collection<? extends TypeValue> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public void clear()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean contains(Object value)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean containsAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean isEmpty()
				{
					return SortedMapAVL.this.entrySet.isEmpty();
				}

				@Override
				public Iterator<TypeValue> iterator()
				{
					return new Iterator<TypeValue>()
					{
						Iterator<Entry<TypeKey, TypeValue>> iterator = SortedMapAVL.this.entrySet.iterator();

						@Override
						public boolean hasNext()
						{
							return this.iterator.hasNext();
						}

						@Override
						public TypeValue next()
						{
							return this.iterator.next().getValue();
						}
					};
				}

				@Override
				public boolean remove(Object o)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean removeAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public boolean retainAll(Collection<?> collection)
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public int size()
				{
					return SortedMapAVL.this.entrySet.size();
				}

				@Override
				public Object[] toArray()
				{
					throw new UnsupportedOperationException();
				}

				@Override
				public <T> T[] toArray(T[] ts)
				{
					throw new UnsupportedOperationException();
				}
			};
		}
	}

	public static class SortedSetAVL<Type>
		implements SortedSet<Type>
	{
		public Comparator<? super Type> comparator;
		public Node<Type> root;

		private SortedSetAVL(
			Comparator<? super Type> comparator,
			Node<Type> root
		)
		{
			this.comparator = comparator;
			this.root = root;
		}

		public SortedSetAVL(Comparator<? super Type> comparator)
		{
			this(
				comparator,
				null
			);
		}

		public SortedSetAVL(
			Collection<? extends Type> collection,
			Comparator<? super Type> comparator
		)
		{
			this(
				comparator,
				null
			);
			this.addAll(collection);
		}

		public SortedSetAVL(SortedSetAVL<Type> sortedSetAVL)
		{
			this(
				sortedSetAVL.comparator,
				Node.clone(sortedSetAVL.root)
			);
		}

		@Override
		public boolean add(Type value)
		{
			int sizeBefore = size();
			this.root = Node.insert(
				this.root,
				value,
				this.comparator
			);
			return sizeBefore != size();
		}

		@Override
		public boolean addAll(Collection<? extends Type> collection)
		{
			return collection.stream()
				.map(this::add)
				.reduce(
					true,
					(x, y) -> x | y
				);
		}

		@Override
		public void clear()
		{
			this.root = null;
		}

		@Override
		public Comparator<? super Type> comparator()
		{
			return this.comparator;
		}

		@Override
		public boolean contains(Object value)
		{
			return Node.get(
				this.root,
				(Type) value,
				this.comparator
			) != null;
		}

		@Override
		public boolean containsAll(Collection<?> collection)
		{
			return collection.stream()
				.allMatch(this::contains);
		}

		@Override
		public Type first()
		{
			return Node.first(this.root).value;
		}

		public Type get(Type value)
		{
			Node<Type> node = Node.get(
				this.root,
				value,
				this.comparator
			);
			return node == null ? null : node.value;
		}

		@Override
		public SortedSetAVL<Type> headSet(Type valueEnd)
		{
			return new SortedSetAVL<>(
				this.comparator,
				Node.head(
					this.root,
					valueEnd,
					this.comparator
				)
			);
		}

		@Override
		public boolean isEmpty()
		{
			return this.root == null;
		}

		@Override
		public Iterator<Type> iterator()
		{
			Stack<Node<Type>> path = new Stack<>();
			return new Iterator<Type>()
			{
				{
					push(SortedSetAVL.this.root);
				}

				@Override
				public boolean hasNext()
				{
					return !path.isEmpty();
				}

				@Override
				public Type next()
				{
					if (path.isEmpty())
					{
						throw new NoSuchElementException();
					}
					else
					{
						Node<Type> node = path.peek();
						Type result = node.value;
						if (node.right != null)
						{
							push(node.right);
						}
						else
						{
							do
							{
								node = path.pop();
							}
							while (!path.isEmpty() && path.peek().right == node);
						}
						return result;
					}
				}

				public void push(Node<Type> node)
				{
					while (node != null)
					{
						path.push(node);
						node = node.left;
					}
				}
			};
		}

		@Override
		public Type last()
		{
			return Node.last(this.root).value;
		}

		@Override
		public boolean remove(Object value)
		{
			int sizeBefore = size();
			this.root = Node.delete(
				this.root,
				(Type) value,
				this.comparator
			);
			return sizeBefore != size();
		}

		@Override
		public boolean removeAll(Collection<?> collection)
		{
			return collection.stream()
				.map(this::remove)
				.reduce(
					true,
					(x, y) -> x | y
				);
		}

		@Override
		public boolean retainAll(Collection<?> collection)
		{
			SortedSetAVL<Type> set = new SortedSetAVL<>(this.comparator);
			collection.stream()
				.map(element -> (Type) element)
				.filter(this::contains)
				.forEach(set::add);
			boolean result = size() != set.size();
			this.root = set.root;
			return result;
		}

		@Override
		public int size()
		{
			return this.root == null ? 0 : this.root.size;
		}

		@Override
		public SortedSetAVL<Type> subSet(
			Type valueStart,
			Type valueEnd
		)
		{
			return tailSet(valueStart).headSet(valueEnd);
		}

		@Override
		public SortedSetAVL<Type> tailSet(Type valueStart)
		{
			return new SortedSetAVL<>(
				this.comparator,
				Node.tail(
					this.root,
					valueStart,
					this.comparator
				)
			);
		}

		@Override
		public Object[] toArray()
		{
			return toArray(new Object[0]);
		}

		@Override
		public <T> T[] toArray(T[] ts)
		{
			List<Object> list = new ArrayList<>();
			Node.traverseOrderIn(
				this.root,
				list::add
			);
			return list.toArray(ts);
		}

		@Override
		public String toString()
		{
			return "{" + F_515.toString(
				this,
				", "
			) + "}";
		}
	}

	public static class Tree2D
	{
		public static final int SIZE = 1 << 30;
		public static final Tree2D[] TREES_NULL = new Tree2D[] { null, null, null, null };

		public static boolean contains(
			int x,
			int y,
			int left,
			int bottom,
			int size
		)
		{
			return left <= x && x < left + size && bottom <= y && y < bottom + size;
		}

		public static int count(Tree2D[] trees)
		{
			int result = 0;
			for (int index = 0; index < 4; index++)
			{
				if (trees[index] != null)
				{
					result += trees[index].count;
				}
			}
			return result;
		}

		public static int count
			(
				int rectangleLeft,
				int rectangleBottom,
				int rectangleRight,
				int rectangleTop,
				Tree2D tree,
				int left,
				int bottom,
				int size
			)
		{
			int result;
			if (tree == null)
			{
				result = 0;
			}
			else
			{
				int right = left + size;
				int top = bottom + size;
				int intersectionLeft = Math.max(
					rectangleLeft,
					left
				);
				int intersectionBottom = Math.max(
					rectangleBottom,
					bottom
				);
				int intersectionRight = Math.min(
					rectangleRight,
					right
				);
				int intersectionTop = Math.min(
					rectangleTop,
					top
				);
				if (intersectionRight <= intersectionLeft || intersectionTop <= intersectionBottom)
				{
					result = 0;
				}
				else
				{
					if (intersectionLeft == left && intersectionBottom == bottom && intersectionRight == right && intersectionTop == top)
					{
						result = tree.count;
					}
					else
					{
						size = size >> 1;
						result = 0;
						for (int index = 0; index < 4; index++)
						{
							result += count
								(
									rectangleLeft,
									rectangleBottom,
									rectangleRight,
									rectangleTop,
									tree.trees[index],
									quadrantLeft(
										left,
										size,
										index
									),
									quadrantBottom(
										bottom,
										size,
										index
									),
									size
								);
						}
					}
				}
			}
			return result;
		}

		public static int quadrantBottom(
			int bottom,
			int size,
			int index
		)
		{
			return bottom + (index >> 1) * size;
		}

		public static int quadrantLeft(
			int left,
			int size,
			int index
		)
		{
			return left + (index & 1) * size;
		}

		public final Tree2D[] trees;
		public final int count;

		private Tree2D(
			Tree2D[] trees,
			int count
		)
		{
			this.trees = trees;
			this.count = count;
		}

		public Tree2D(Tree2D[] trees)
		{
			this(
				trees,
				count(trees)
			);
		}

		public Tree2D()
		{
			this(TREES_NULL);
		}

		public int count(
			int rectangleLeft,
			int rectangleBottom,
			int rectangleRight,
			int rectangleTop
		)
		{
			return count
				(
					rectangleLeft,
					rectangleBottom,
					rectangleRight,
					rectangleTop,
					this,
					0,
					0,
					SIZE
				);
		}

		public Tree2D setPoint
			(
				int x,
				int y,
				Tree2D tree,
				int left,
				int bottom,
				int size
			)
		{
			Tree2D result;
			if (contains(
				x,
				y,
				left,
				bottom,
				size
			))
			{
				if (size == 1)
				{
					result = new Tree2D(
						TREES_NULL,
						1
					);
				}
				else
				{
					size = size >> 1;
					Tree2D[] trees = new Tree2D[4];
					for (int index = 0; index < 4; index++)
					{
						trees[index] = setPoint
							(
								x,
								y,
								tree == null ? null : tree.trees[index],
								quadrantLeft(
									left,
									size,
									index
								),
								quadrantBottom(
									bottom,
									size,
									index
								),
								size
							);
					}
					result = new Tree2D(trees);
				}
			}
			else
			{
				result = tree;
			}
			return result;
		}

		public Tree2D setPoint(
			int x,
			int y
		)
		{
			return setPoint
				(
					x,
					y,
					this,
					0,
					0,
					SIZE
				);
		}
	}

	public static class Tuple2<Type0, Type1>
	{
		public final Type0 v0;
		public final Type1 v1;

		public Tuple2(
			Type0 v0,
			Type1 v1
		)
		{
			this.v0 = v0;
			this.v1 = v1;
		}

		@Override
		public String toString()
		{
			return "(" + this.v0 + ", " + this.v1 + ")";
		}
	}

	public static class Tuple2Comparable<Type0 extends Comparable<? super Type0>, Type1 extends Comparable<? super Type1>>
		extends Tuple2<Type0, Type1>
		implements Comparable<Tuple2Comparable<Type0, Type1>>
	{
		public Tuple2Comparable(
			Type0 v0,
			Type1 v1
		)
		{
			super(
				v0,
				v1
			);
		}

		@Override
		public int compareTo(Tuple2Comparable<Type0, Type1> that)
		{
			int result = this.v0.compareTo(that.v0);
			if (result == 0)
			{
				result = this.v1.compareTo(that.v1);
			}
			return result;
		}
	}

	public static class Tuple3<Type0, Type1, Type2>
	{
		public final Type0 v0;
		public final Type1 v1;
		public final Type2 v2;

		public Tuple3(
			Type0 v0,
			Type1 v1,
			Type2 v2
		)
		{
			this.v0 = v0;
			this.v1 = v1;
			this.v2 = v2;
		}

		@Override
		public String toString()
		{
			return "(" + this.v0 + ", " + this.v1 + ", " + this.v2 + ")";
		}
	}

	public static class Vertex
		<
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		implements Comparable<Vertex<? super TypeVertex, ? super TypeEdge>>
	{
		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>,
			TypeResult
			> TypeResult breadthFirstSearch
			(
				TypeVertex vertex,
				TypeEdge edge,
				BiFunctionResult<TypeVertex, TypeEdge, TypeResult> function,
				Array<Boolean> visited,
				FIFO<TypeVertex> verticesNext,
				FIFO<TypeEdge> edgesNext,
				TypeResult result
			)
		{
			if (!visited.get(vertex.index))
			{
				visited.set(
					vertex.index,
					true
				);
				result = function.apply(
					vertex,
					edge,
					result
				);
				for (TypeEdge edgeNext : vertex.edges)
				{
					TypeVertex vertexNext = edgeNext.other(vertex);
					if (!visited.get(vertexNext.index))
					{
						verticesNext.push(vertexNext);
						edgesNext.push(edgeNext);
					}
				}
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>,
			TypeResult
			>
		TypeResult breadthFirstSearch
			(
				Array<TypeVertex> vertices,
				int indexVertexStart,
				BiFunctionResult<TypeVertex, TypeEdge, TypeResult> function,
				TypeResult result
			)
		{
			Array<Boolean> visited = new Array<>(
				vertices.size(),
				false
			);
			FIFO<TypeVertex> verticesNext = new FIFO<>();
			verticesNext.push(vertices.get(indexVertexStart));
			FIFO<TypeEdge> edgesNext = new FIFO<>();
			edgesNext.push(null);
			while (!verticesNext.isEmpty())
			{
				result = breadthFirstSearch(
					verticesNext.pop(),
					edgesNext.pop(),
					function,
					visited,
					verticesNext,
					edgesNext,
					result
				);
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		boolean
		cycle
			(
				TypeVertex start,
				SortedSet<TypeVertex> result
			)
		{
			boolean cycle = false;
			Stack<TypeVertex> stackVertex = new Stack<>();
			Stack<TypeEdge> stackEdge = new Stack<>();
			stackVertex.push(start);
			stackEdge.push(null);
			while (!stackVertex.isEmpty())
			{
				TypeVertex vertex = stackVertex.pop();
				TypeEdge edge = stackEdge.pop();
				if (!result.contains(vertex))
				{
					result.add(vertex);
					for (TypeEdge otherEdge : vertex.edges)
					{
						if (otherEdge != edge)
						{
							TypeVertex otherVertex = otherEdge.other(vertex);
							if (result.contains(otherVertex))
							{
								cycle = true;
							}
							else
							{
								stackVertex.push(otherVertex);
								stackEdge.push(otherEdge);
							}
						}
					}
				}
			}
			return cycle;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		SortedSet<TypeVertex>
		depthFirstSearch
			(
				TypeVertex start,
				BiConsumer<TypeVertex, TypeEdge> functionVisitPre,
				BiConsumer<TypeVertex, TypeEdge> functionVisitPost
			)
		{
			SortedSet<TypeVertex> result = new SortedSetAVL<>(Comparator.naturalOrder());
			Stack<TypeVertex> stackVertex = new Stack<>();
			Stack<TypeEdge> stackEdge = new Stack<>();
			stackVertex.push(start);
			stackEdge.push(null);
			while (!stackVertex.isEmpty())
			{
				TypeVertex vertex = stackVertex.pop();
				TypeEdge edge = stackEdge.pop();
				if (result.contains(vertex))
				{
					functionVisitPost.accept(
						vertex,
						edge
					);
				}
				else
				{
					result.add(vertex);
					stackVertex.push(vertex);
					stackEdge.push(edge);
					functionVisitPre.accept(
						vertex,
						edge
					);
					for (TypeEdge otherEdge : vertex.edges)
					{
						TypeVertex otherVertex = otherEdge.other(vertex);
						if (!result.contains(otherVertex))
						{
							stackVertex.push(otherVertex);
							stackEdge.push(otherEdge);
						}
					}
				}
			}
			return result;
		}

		public static <
			TypeVertex extends Vertex<TypeVertex, TypeEdge>,
			TypeEdge extends Edge<TypeVertex, TypeEdge>
			>
		SortedSet<TypeVertex>
		depthFirstSearch
			(
				TypeVertex start,
				Consumer<TypeVertex> functionVisitPreVertex,
				Consumer<TypeVertex> functionVisitPostVertex
			)
		{
			BiConsumer<TypeVertex, TypeEdge> functionVisitPreVertexEdge = (vertex, edge) ->
			{
				functionVisitPreVertex.accept(vertex);
			};
			BiConsumer<TypeVertex, TypeEdge> functionVisitPostVertexEdge = (vertex, edge) ->
			{
				functionVisitPostVertex.accept(vertex);
			};
			return depthFirstSearch(
				start,
				functionVisitPreVertexEdge,
				functionVisitPostVertexEdge
			);
		}

		public final int index;
		public final List<TypeEdge> edges;

		public Vertex(int index)
		{
			this.index = index;
			this.edges = new ArrayList<>();
		}

		@Override
		public int compareTo(Vertex<? super TypeVertex, ? super TypeEdge> that)
		{
			return Integer.compare(
				this.index,
				that.index
			);
		}

		@Override
		public String toString()
		{
			return "" + this.index;
		}
	}

	public static class VertexDefault<TypeEdge extends Edge<VertexDefault<TypeEdge>, TypeEdge>>
		extends Vertex<VertexDefault<TypeEdge>, TypeEdge>
	{
		public VertexDefault(int index)
		{
			super(index);
		}
	}

	public static class VertexDefaultDefault
		extends Vertex<VertexDefaultDefault, EdgeDefaultDefault>
	{
		public static Array<VertexDefaultDefault> vertices(int n)
		{
			Array<VertexDefaultDefault> result = new Array<>(n);
			for (int index = 0; index < n; index++)
			{
				result.set(
					index,
					new VertexDefaultDefault(index)
				);
			}
			return result;
		}

		public VertexDefaultDefault(int index)
		{
			super(index);
		}
	}

	public static class Wrapper<Type>
	{
		public Type value;

		public Wrapper(Type value)
		{
			this.value = value;
		}

		public Type get()
		{
			return this.value;
		}

		public void set(Type value)
		{
			this.value = value;
		}

		@Override
		public String toString()
		{
			return this.value.toString();
		}
	}

	public static void add(
		int delta,
		int[] result
	)
	{
		for (int index = 0; index < result.length; index++)
		{
			result[index] += delta;
		}
	}

	public static void add(
		int delta,
		int[]... result
	)
	{
		for (int index = 0; index < result.length; index++)
		{
			add(
				delta,
				result[index]
			);
		}
	}

	public static long add(
		long x,
		long y
	)
	{
		return (x + y) % BIG;
	}

	public static int binarySearchMaximum(
		Function<Integer, Boolean> filter,
		int start,
		int end
	)
	{
		return -binarySearchMinimum(
			x -> filter.apply(-x),
			-end,
			-start
		);
	}

	public static int binarySearchMinimum(
		Function<Integer, Boolean> filter,
		int start,
		int end
	)
	{
		int result;
		if (start == end)
		{
			result = end;
		}
		else
		{
			int middle = start + (end - start) / 2;
			if (filter.apply(middle))
			{
				result = binarySearchMinimum(
					filter,
					start,
					middle
				);
			}
			else
			{
				result = binarySearchMinimum(
					filter,
					middle + 1,
					end
				);
			}
		}
		return result;
	}

	public static void close()
	{
		out.close();
	}

	private static void combinations(
		int n,
		int k,
		int start,
		SortedSet<Integer> combination,
		List<SortedSet<Integer>> result
	)
	{
		if (k == 0)
		{
			result.add(new SortedSetAVL<>(
				combination,
				Comparator.naturalOrder()
			));
		}
		else
		{
			for (int index = start; index < n; index++)
			{
				if (!combination.contains(index))
				{
					combination.add(index);
					combinations(
						n,
						k - 1,
						index + 1,
						combination,
						result
					);
					combination.remove(index);
				}
			}
		}
	}

	public static List<SortedSet<Integer>> combinations(
		int n,
		int k
	)
	{
		List<SortedSet<Integer>> result = new ArrayList<>();
		combinations(
			n,
			k,
			0,
			new SortedSetAVL<>(Comparator.naturalOrder()),
			result
		);
		return result;
	}

	public static <Type> int compare(
		Iterator<Type> iterator0,
		Iterator<Type> iterator1,
		Comparator<Type> comparator
	)
	{
		int result = 0;
		while (result == 0 && iterator0.hasNext() && iterator1.hasNext())
		{
			result = comparator.compare(
				iterator0.next(),
				iterator1.next()
			);
		}
		if (result == 0)
		{
			if (iterator1.hasNext())
			{
				result = -1;
			}
			else
			{
				if (iterator0.hasNext())
				{
					result = 1;
				}
			}
		}
		return result;
	}

	public static <Type> int compare(
		Iterable<Type> iterable0,
		Iterable<Type> iterable1,
		Comparator<Type> comparator
	)
	{
		return compare(
			iterable0.iterator(),
			iterable1.iterator(),
			comparator
		);
	}

	public static long divideCeil(
		long x,
		long y
	)
	{
		return (x + y - 1) / y;
	}

	public static Set<Long> divisors(long n)
	{
		SortedSetAVL<Long> result = new SortedSetAVL<>(Comparator.naturalOrder());
		result.add(1L);
		for (Long factor : factors(n))
		{
			SortedSetAVL<Long> divisors = new SortedSetAVL<>(result);
			for (Long divisor : result)
			{
				divisors.add(divisor * factor);
			}
			result = divisors;
		}
		return result;
	}

	public static LinkedList<Long> factors(long n)
	{
		LinkedList<Long> result = new LinkedList<>();
		Iterator<Long> primes = ITERATOR_BUFFER_PRIME.iterator();
		Long prime;
		while (n > 1 && (prime = primes.next()) * prime <= n)
		{
			while (n % prime == 0)
			{
				result.add(prime);
				n /= prime;
			}
		}
		if (n > 1)
		{
			result.add(n);
		}
		return result;
	}

	public static long faculty(int n)
	{
		long result = 1;
		for (int index = 2; index <= n; index++)
		{
			result *= index;
		}
		return result;
	}

	static long gcd(
		long a,
		long b
	)
	{
		return b == 0 ? a : gcd(
			b,
			a % b
		);
	}

	public static long[] generatePOWER2()
	{
		long[] result = new long[63];
		for (int x = 0; x < result.length; x++)
		{
			result[x] = 1L << x;
		}
		return result;
	}

	public static boolean isPrime(long x)
	{
		boolean result = x > 1;
		Iterator<Long> iterator = ITERATOR_BUFFER_PRIME.iterator();
		Long prime;
		while ((prime = iterator.next()) * prime <= x)
		{
			result &= x % prime > 0;
		}
		return result;
	}

	public static long knapsack(
		List<Tuple3<Long, Integer, Integer>> itemsValueWeightCount,
		int weightMaximum
	)
	{
		long[] valuesMaximum = new long[weightMaximum + 1];
		for (Tuple3<Long, Integer, Integer> itemValueWeightCount : itemsValueWeightCount)
		{
			long itemValue = itemValueWeightCount.v0;
			int itemWeight = itemValueWeightCount.v1;
			int itemCount = itemValueWeightCount.v2;
			for (int weight = weightMaximum; 0 <= weight; weight--)
			{
				for (int index = 1; index <= itemCount && 0 <= weight - index * itemWeight; index++)
				{
					valuesMaximum[weight] = Math.max(
						valuesMaximum[weight],
						valuesMaximum[weight - index * itemWeight] + index * itemValue
					);
				}
			}
		}
		long result = 0;
		for (long valueMaximum : valuesMaximum)
		{
			result = Math.max(
				result,
				valueMaximum
			);
		}
		return result;
	}

	public static boolean knapsackPossible(
		List<Tuple2<Integer, Integer>> itemsWeightCount,
		int weightMaximum
	)
	{
		boolean[] weightPossible = new boolean[weightMaximum + 1];
		weightPossible[0] = true;
		int weightLargest = 0;
		for (Tuple2<Integer, Integer> itemWeightCount : itemsWeightCount)
		{
			int itemWeight = itemWeightCount.v0;
			int itemCount = itemWeightCount.v1;
			for (int weightStart = 0; weightStart < itemWeight; weightStart++)
			{
				int count = 0;
				for (int weight = weightStart; weight <= weightMaximum && (0 < count || weight <= weightLargest); weight += itemWeight)
				{
					if (weightPossible[weight])
					{
						count = itemCount;
					}
					else
					{
						if (0 < count)
						{
							weightPossible[weight] = true;
							weightLargest = weight;
							count -= 1;
						}
					}
				}
			}
		}
		return weightPossible[weightMaximum];
	}

	public static long lcm(
		int a,
		int b
	)
	{
		return a * b / gcd(
			a,
			b
		);
	}

	public static void main(String[] args)
	{
		try
		{
			solve();
		}
		catch (IOException exception)
		{
			exception.printStackTrace();
		}
		close();
	}

	public static long mul(
		long x,
		long y
	)
	{
		return (x * y) % BIG;
	}

	public static double nextDouble()
		throws IOException
	{
		return Double.parseDouble(nextString());
	}

	public static int nextInt()
		throws IOException
	{
		return Integer.parseInt(nextString());
	}

	public static void nextInts(
		int n,
		int[]... result
	)
		throws IOException
	{
		for (int index = 0; index < n; index++)
		{
			for (int value = 0; value < result.length; value++)
			{
				result[value][index] = nextInt();
			}
		}
	}

	public static int[] nextInts(int n)
		throws IOException
	{
		int[] result = new int[n];
		nextInts(
			n,
			result
		);
		return result;
	}

	public static String nextLine()
		throws IOException
	{
		return bufferedReader.readLine();
	}

	public static long nextLong()
		throws IOException
	{
		return Long.parseLong(nextString());
	}

	public static void nextLongs(
		int n,
		long[]... result
	)
		throws IOException
	{
		for (int index = 0; index < n; index++)
		{
			for (int value = 0; value < result.length; value++)
			{
				result[value][index] = nextLong();
			}
		}
	}

	public static long[] nextLongs(int n)
		throws IOException
	{
		long[] result = new long[n];
		nextLongs(
			n,
			result
		);
		return result;
	}

	public static String nextString()
		throws IOException
	{
		while ((stringTokenizer == null) || (!stringTokenizer.hasMoreTokens()))
		{
			stringTokenizer = new StringTokenizer(bufferedReader.readLine());
		}
		return stringTokenizer.nextToken();
	}

	public static String[] nextStrings(int n)
		throws IOException
	{
		String[] result = new String[n];
		{
			for (int index = 0; index < n; index++)
			{
				result[index] = nextString();
			}
		}
		return result;
	}

	public static <T> List<T> permutation(
		long p,
		List<T> x
	)
	{
		List<T> copy = new ArrayList<>();
		for (int index = 0; index < x.size(); index++)
		{
			copy.add(x.get(index));
		}
		List<T> result = new ArrayList<>();
		for (int indexTo = 0; indexTo < x.size(); indexTo++)
		{
			int indexFrom = (int) p % copy.size();
			p = p / copy.size();
			result.add(copy.remove(indexFrom));
		}
		return result;
	}

	public static <Type> List<List<Type>> permutations(List<Type> list)
	{
		List<List<Type>> result = new ArrayList<>();
		result.add(new ArrayList<>());
		for (Type element : list)
		{
			List<List<Type>> permutations = result;
			result = new ArrayList<>();
			for (List<Type> permutation : permutations)
			{
				for (int index = 0; index <= permutation.size(); index++)
				{
					List<Type> permutationNew = new ArrayList<>(permutation);
					permutationNew.add(
						index,
						element
					);
					result.add(permutationNew);
				}
			}
		}
		return result;
	}

	public static long[][] sizeGroup2CombinationsCount(int maximum)
	{
		long[][] result = new long[maximum + 1][maximum + 1];
		for (int length = 0; length <= maximum; length++)
		{
			result[length][0] = 1;
			for (int group = 1; group <= length; group++)
			{
				result[length][group] = add(
					result[length - 1][group - 1],
					result[length - 1][group]
				);
			}
		}
		return result;
	}

	public static Stream<BigInteger> streamFibonacci()
	{
		return Stream.generate(new Supplier<BigInteger>()
		{
			private BigInteger n0 = BigInteger.ZERO;
			private BigInteger n1 = BigInteger.ONE;

			@Override
			public BigInteger get()
			{
				BigInteger result = n0;
				n0 = n1;
				n1 = result.add(n0);
				return result;
			}
		});
	}

	public static Stream<Long> streamPrime(int sieveSize)
	{
		return Stream.generate(new Supplier<Long>()
		{
			private boolean[] isPrime = new boolean[sieveSize];
			private long sieveOffset = 2;
			private List<Long> primes = new ArrayList<>();
			private int index = 0;

			public void filter(
				long prime,
				boolean[] result
			)
			{
				if (prime * prime < this.sieveOffset + sieveSize)
				{
					long remainingStart = this.sieveOffset % prime;
					long start = remainingStart == 0 ? 0 : prime - remainingStart;
					for (long index = start; index < sieveSize; index += prime)
					{
						result[(int) index] = false;
					}
				}
			}

			public void generatePrimes()
			{
				Arrays.fill(
					this.isPrime,
					true
				);
				this.primes.forEach(prime -> filter(
					prime,
					isPrime
				));
				for (int index = 0; index < sieveSize; index++)
				{
					if (isPrime[index])
					{
						this.primes.add(this.sieveOffset + index);
						filter(
							this.sieveOffset + index,
							isPrime
						);
					}
				}
				this.sieveOffset += sieveSize;
			}

			@Override
			public Long get()
			{
				while (this.primes.size() <= this.index)
				{
					generatePrimes();
				}
				Long result = this.primes.get(this.index);
				this.index += 1;
				return result;
			}
		});
	}

	public static <Type> String toString(
		Iterator<Type> iterator,
		String separator
	)
	{
		StringBuilder stringBuilder = new StringBuilder();
		if (iterator.hasNext())
		{
			stringBuilder.append(iterator.next());
		}
		while (iterator.hasNext())
		{
			stringBuilder.append(separator);
			stringBuilder.append(iterator.next());
		}
		return stringBuilder.toString();
	}

	public static <Type> String toString(Iterator<Type> iterator)
	{
		return toString(
			iterator,
			" "
		);
	}

	public static <Type> String toString(
		Iterable<Type> iterable,
		String separator
	)
	{
		return toString(
			iterable.iterator(),
			separator
		);
	}

	public static <Type> String toString(Iterable<Type> iterable)
	{
		return toString(
			iterable,
			" "
		);
	}

	public static long totient(long n)
	{
		Set<Long> factors = new SortedSetAVL<>(
			factors(n),
			Comparator.naturalOrder()
		);
		long result = n;
		for (long p : factors)
		{
			result -= result / p;
		}
		return result;
	}

	interface BiFunctionResult<Type0, Type1, TypeResult>
	{
		TypeResult apply(
			Type0 x0,
			Type1 x1,
			TypeResult x2
		);
	}

	static class Point
		implements Comparable<Point>
	{
		public final int x;
		public final int y;

		@Override
		public int compareTo(Point that)
		{
			int result = Integer.compare(
				this.x,
				that.x
			);
			if (result == 0)
			{
				result = Integer.compare(
					this.y,
					that.y
				);
			}
			return result;
		}

		public Point(
			int x,
			int y
		)
		{
			this.x = x;
			this.y = y;
		}

		public int level()
		{
			return Math.max(
				this.x,
				this.y
			);
		}

		public long distance(Point point)
		{
			return Math.abs(this.x - point.x) + Math.abs(this.y - point.y);
		}

		public String toString()
		{
			return "(" + this.x + ", " + this.y + ")";
		}
	}

	public static Point min
		(
			Set<Point> points,
			Function<Point, Integer> function1,
			Function<Point, Integer> function2
		)
	{
		Iterator<Point> iterator = points.iterator();
		Point result = iterator.next();
		while (iterator.hasNext())
		{
			Point point = iterator.next();
			if (function1.apply(point) < function1.apply(result))
			{
				result = point;
			}
			else
			{
				if (function1.apply(point) == function1.apply(result) && function2.apply(point) < function2.apply(result))
				{
					result = point;
				}
			}
		}
		return result;
	}

	public static void solve()
		throws IOException
	{
		int n = nextInt();
		MapSet<Integer, Point> level2Points = new MapSet<>(
			Comparator.naturalOrder(),
			Comparator.naturalOrder()
		);
		for (int index = 0; index < n; index++)
		{
			Point point = new Point(
				nextInt(),
				nextInt()
			);
			level2Points.add(
				point.level(),
				point
			);
		}
		long resultLeft = 0;
		long resultDown = 0;
		Point lastLeft = new Point(
			0,
			0
		);
		Point lastDown = new Point(
			0,
			0
		);
		for (Map.Entry<Integer, SortedSetAVL<Point>> entry : level2Points.entrySet)
		{
			Set<Point> points = entry.getValue();
			Point left = min
				(
					points,
					point -> point.x,
					point -> -point.y
				);
			Point down = min
				(
					points,
					point -> point.y,
					point -> -point.x
				);
			long distanceLevel = down.distance(left);
			long resultLeftNew = Math.min
				(
					resultLeft + lastLeft.distance(down),
					resultDown + lastDown.distance(down)
				) + distanceLevel;
			long resultDownNew = Math.min
				(
					resultLeft + lastLeft.distance(left),
					resultDown + lastDown.distance(down)
				) + distanceLevel;
			resultLeft = resultLeftNew;
			resultDown = resultDownNew;
			lastLeft = left;
			lastDown = down;
		}
		out.println(Math.min(
			resultDown,
			resultLeft
		));
	}
}

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class ProblemF {

    static class Point {
        long x;
        long y;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Map<Long, Point> left = new HashMap<>();
        Map<Long, Point> right = new HashMap<>();
        for(int i=0;i<n;i++) {
            long x = sc.nextInt();
            long y = sc.nextInt();
            long l = Math.max(x, y);
            if(!left.containsKey(l)) {
                left.put(l, new Point(x, y));
            } else if(left.get(l).x > x){
                left.put(l, new Point(x, y));
            } else if(left.get(l).x == x){
                left.put(l, new Point(x, Math.max(y, left.get(l).y)));
            }
            if(!right.containsKey(l)) {
                right.put(l, new Point(x, y));
            } else if(right.get(l).y > y) {
                right.put(l, new Point(x, y));
            } else if(left.get(l).y == y){
                right.put(l, new Point(Math.max(right.get(l).x, x), y));
            }
        }
        long lans = 0;
        long plans = 0;
        long rans = 0;
        long prans = 0;
        Point pvsl = new Point(0, 0);
        Point pvsr = new Point(0, 0);
        for(long i=1;i <= 200000; i++ ) {
            if(!left.containsKey(i)) {
                continue;
            }
            Point lp = left.get(i);
            Point rp = right.get(i);
//            System.out.println(lp.x + " " + lp.y + " " + rp.x + " " + rp.y);
            rans = dist(lp, rp) + Math.min(plans + dist(lp, pvsl), prans + dist(lp, pvsr));
            lans = dist(lp, rp) + Math.min(plans + dist(rp, pvsl), prans + dist(rp, pvsr));
//            System.out.println(lans + " " + rans);
            pvsl = lp;
            pvsr = rp;
            plans = lans;
            prans = rans;
        }
        System.out.println(Math.min(lans, rans));
    }

    public static long dist(Point p1, Point p2) {
        return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
    }

}

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class ProblemF {

    static class Point {
        long x;
        long y;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Map<Long, Point> left = new HashMap<>();
        Map<Long, Point> right = new HashMap<>();
        for(int i=0;i<n;i++) {
            long x = sc.nextInt();
            long y = sc.nextInt();
            long l = Math.max(x, y);
            if(!left.containsKey(l)) {
                left.put(l, new Point(x, y));
            } else if(left.get(l).x > x){
                left.put(l, new Point(x, y));
            } else if(left.get(l).x == x){
                left.put(l, new Point(x, Math.max(y, left.get(l).y)));
            }
            if(!right.containsKey(l)) {
                right.put(l, new Point(x, y));
            } else if(right.get(l).y > y) {
                right.put(l, new Point(x, y));
            } else if(right.get(l).y == y){
                right.put(l, new Point(Math.max(right.get(l).x, x), y));
            }
        }
        long lans = 0;
        long plans = 0;
        long rans = 0;
        long prans = 0;
        Point pvsl = new Point(0, 0);
        Point pvsr = new Point(0, 0);
        for(long i=1;i <= 200000; i++ ) {
            if(!left.containsKey(i)) {
                continue;
            }
            Point lp = left.get(i);
            Point rp = right.get(i);
//            System.out.println(lp.x + " " + lp.y + " " + rp.x + " " + rp.y);
            rans = dist(lp, rp) + Math.min(plans + dist(lp, pvsl), prans + dist(lp, pvsr));
            lans = dist(lp, rp) + Math.min(plans + dist(rp, pvsl), prans + dist(rp, pvsr));
//            System.out.println(lans + " " + rans);
            pvsl = lp;
            pvsr = rp;
            plans = lans;
            prans = rans;
        }
        System.out.println(Math.min(lans, rans));
    }

    public static long dist(Point p1, Point p2) {
        return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
    }

}

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringTokenizer;

import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.round;
import static java.util.Arrays.copyOf;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;
import static java.util.Collections.reverseOrder;
import static java.util.Collections.sort;
import static java.util.Comparator.comparing;

public class Main {
    FastScanner in;
    PrintWriter out;

    class Point {
        int x, y, max;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
            max = max(x, y);
        }
    }

    long dist(Point a, Point b) {
        return abs(a.x - b.x) + abs(a.y - b.y);
    }

    private void solve() throws IOException {
        int n = in.nextInt();
        Point[] p = new Point[n];
        for (int i = 0; i < n; i++)
            p[i] = new Point(in.nextInt(), in.nextInt());

        sort(p, (o1, o2) -> o1.max != o2.max ? o1.max - o2.max : o1.x != o2.x ? o1.x - o2.x : o1.y - o2.y);

        long[] dist = new long[2];
        long pd;
        Point[] last = new Point[]{new Point(0, 0), new Point(0, 0)};
        for (int l = 0, r = 0; l < n; l = r) {
            while (r < n && p[r].max == p[l].max)
                r++;

            pd = dist[0];
            dist[0] = min(dist[0] + dist(last[0], p[r - 1]), dist[1] + dist(last[1], p[r - 1])) + dist(p[l], p[r - 1]);
            dist[1] = min(pd + dist(last[0], p[l]), dist[1] + dist(last[1], p[l])) + dist(p[l], p[r - 1]);
            last[0] = p[l];
            last[1] = p[r - 1];
        }
        out.println(min(dist[0], dist[1]));
    }

    class FastScanner {
        StringTokenizer st;
        BufferedReader br;

        FastScanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        boolean hasNext() throws IOException {
            return br.ready() || (st != null && st.hasMoreTokens());
        }

        int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        String nextLine() throws IOException {
            return br.readLine();
        }

        boolean hasNextLine() throws IOException {
            return br.ready();
        }
    }

    private void run() throws IOException {
        in = new FastScanner(System.in); // new FastScanner(new FileInputStream("input.txt"));
        out = new PrintWriter(System.out); // new PrintWriter(new FileOutputStream("output.txt"));

        solve();

        out.flush();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new Main().run();
    }
}

/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main
{
    static Reader scan;
    static PrintWriter pw;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<25)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static void solve() throws IOException
    {
        scan = new Reader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        int n = ni();
        TreeMap<Integer, Pair> leftmost = new TreeMap<>();
        TreeMap<Integer, Pair> downmost = new TreeMap<>();
        ArrayList<Integer> levels = new ArrayList<>();
        for(int i=0;i<n;++i) {
            int x = ni(), y = ni();
            int lev = max(x,y);
            if(!leftmost.containsKey(lev)) {
                leftmost.put(lev, new Pair(x,y));
            }
            else {
                Pair p = leftmost.get(lev);
                if(x<p.x) {
                    leftmost.put(lev, new Pair(x,y));
                }
                else if(x==p.x && y<p.y) {
                    leftmost.put(lev, new Pair(x,y));
                }
            }
            if(!downmost.containsKey(lev)) {
                downmost.put(lev, new Pair(x,y));
            }
            else {
                Pair p = downmost.get(lev);
                if(y<p.y) {
                    downmost.put(lev, new Pair(x,y));
                }
                else if(y==p.y && x>p.x) {
                    downmost.put(lev, new Pair(x,y));
                }
            }
        }
        //pl(downmost);
        //pl(leftmost);
        for(int e:leftmost.keySet()) {
            levels.add(e);
        }
        Collections.sort(levels);
        //pa("levels", levels);
        int N = levels.size();
        long dp[][] = new long[N][2];  //0 left, 1 down
        int highest_level = levels.get(N-1);
        dp[N-1][0] = dp[N-1][1] = dis(leftmost.get(highest_level), downmost.get(highest_level));
        for(int i=N-2;i>=0;--i) {
            int lev = levels.get(i);
            int nxtlev = levels.get(i+1);
            Pair foo = leftmost.get(lev);
            Pair bar = downmost.get(lev);
            long travel = dis(foo, bar);
            //pl("i : "+i+" travel : "+travel+" lev : "+lev);
            dp[i][0] = travel + min(dis(downmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1], dis(downmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0]);
            dp[i][1] = travel + min(dis(leftmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0], dis(leftmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1]);
        }
        //pa("DP", dp);
        long ans = min(dis(new Pair(0,0), leftmost.get(levels.get(0))) + dp[0][0], dis(new Pair(0,0), downmost.get(levels.get(0))) + dp[0][1]);
        pl(ans);
        pw.flush();
        pw.close();
    }
    static long dis(Pair p, Pair q) {
        return abs(p.x-q.x) + abs(p.y-q.y);
    }
    static class Pair implements Comparable<Pair>
    {
        int x,y;
        Pair(int x,int y)
        {
            this.x=x;
            this.y=y;
        }
        public int compareTo(Pair other)
        {
            if(this.x!=other.x)
                return this.x-other.x;
            return this.y-other.y;
        }
        public String toString()
        {
            return "("+x+","+y+")";
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[64];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}

/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main
{
    static Reader scan;
    static PrintWriter pw;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<25)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static void solve() throws IOException
    {
        scan = new Reader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        int n = ni();
        TreeMap<Integer, Pair> leftmost = new TreeMap<>();
        TreeMap<Integer, Pair> downmost = new TreeMap<>();
        ArrayList<Integer> levels = new ArrayList<>();
        for(int i=0;i<n;++i) {
            int x = ni(), y = ni();
            int lev = max(x,y);
            if(!leftmost.containsKey(lev)) {
                leftmost.put(lev, new Pair(x,y));
                downmost.put(lev, new Pair(x,y));
            }
            else {
                Pair p = leftmost.get(lev);
                if(x<p.x) {
                    leftmost.put(lev, new Pair(x,y));
                }
                Pair q = downmost.get(lev);
                if(y<q.y) {
                    downmost.put(lev, new Pair(x,y));
                }
            }
        }
        //pl(downmost);
        //pl(leftmost);
        for(int e:leftmost.keySet()) {
            levels.add(e);
        }
        //pa("levels", levels);
        int N = levels.size();
        long dp[][] = new long[N][2];  //0 left, 1 down
        int highest_level = levels.get(N-1);
        dp[N-1][0] = dp[N-1][1] = dis(leftmost.get(highest_level), downmost.get(highest_level));
        for(int i=N-2;i>=0;--i) {
            int lev = levels.get(i);
            int nxtlev = levels.get(i+1);
            Pair foo = leftmost.get(lev);
            Pair bar = downmost.get(lev);
            long travel = dis(foo, bar);
            //pl("i : "+i+" travel : "+travel+" lev : "+lev);
            dp[i][0] = travel + min(dis(downmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1], dis(downmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0]);
            dp[i][1] = travel + min(dis(leftmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0], dis(leftmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1]);
        }
        //pa("DP", dp);
        long ans = min(dis(new Pair(0,0), leftmost.get(levels.get(0))) + dp[0][0], dis(new Pair(0,0), downmost.get(levels.get(0))) + dp[0][1]);
        pl(ans);
        pw.flush();
        pw.close();
    }
    static long dis(Pair p, Pair q) {
        return abs(p.x-q.x) + abs(p.y-q.y);
    }
    static class Pair implements Comparable<Pair>
    {
        int x,y;
        Pair(int x,int y)
        {
            this.x=x;
            this.y=y;
        }
        public int compareTo(Pair other)
        {
            if(this.x!=other.x)
                return this.x-other.x;
            return this.y-other.y;
        }
        public String toString()
        {
            return "("+x+","+y+")";
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[64];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}

/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main
{
    static Reader scan;
    static PrintWriter pw;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<25)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static void solve() throws IOException
    {
        scan = new Reader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        TreeMap<Integer, ArrayList<Pair>> points_at_level = new TreeMap<>();
        Map<Integer, Integer> max_x_at_level = new HashMap<>();
        Map<Integer, Integer> max_y_at_level = new HashMap<>();
        Map<Integer, Integer> min_x_at_level = new HashMap<>();
        Map<Integer, Integer> min_y_at_level = new HashMap<>();
        int n = ni();
        for(int i=0;i<n;++i) {
            int x = ni(), y = ni();
            int iska_level = max(x,y);
            ArrayList<Pair> fuck = points_at_level.get(iska_level);
            if(fuck==null) {
                fuck = new ArrayList<>();
            }
            fuck.add(new Pair(x,y));
            points_at_level.put(iska_level, fuck);
            Integer fucked = max_x_at_level.get(iska_level);
            if(fucked==null) {
                max_x_at_level.put(iska_level, x);
            }
            else {
                max_x_at_level.put(iska_level, max(fucked, x));
            }
            fucked = max_y_at_level.get(iska_level);
            if(fucked==null) {
                max_y_at_level.put(iska_level, y);
            }
            else {
                max_y_at_level.put(iska_level, max(fucked, y));
            }
            fucked = min_x_at_level.get(iska_level);
            if(fucked==null) {
                min_x_at_level.put(iska_level, x);
            }
            else {
                min_x_at_level.put(iska_level, min(x, fucked));
            }
            fucked = min_y_at_level.get(iska_level);
            if(fucked==null) {
                min_y_at_level.put(iska_level, y);
            }
            else {
                min_y_at_level.put(iska_level, min(y, fucked));
            }
        }
        //pl(points_at_level);
        long ans = 0;
        int prevx = 0, prevy = 0;
        for(int e:points_at_level.keySet()) {
                Pair sbse_niche_wala_point = new Pair(Integer.MAX_VALUE, Integer.MAX_VALUE);
                for(Pair p : points_at_level.get(e)) {
                    if(p.y<sbse_niche_wala_point.y) {
                        sbse_niche_wala_point = new Pair(p.x, p.y);
                    }
                }
                Pair sbse_left_wala_point = new Pair(Integer.MAX_VALUE, Integer.MAX_VALUE);
                for(Pair p : points_at_level.get(e)) {
                    if(p.x<sbse_left_wala_point.x) {
                        sbse_left_wala_point = new Pair(p.x, p.y);
                    }
                }
                if(abs(prevx - sbse_left_wala_point.x) + abs(prevy - sbse_left_wala_point.y) <
                   abs(prevx - sbse_niche_wala_point.x) + abs(prevy - sbse_niche_wala_point.y)) {
                    //pehle left phir right down
                    ans+=abs(prevx - sbse_left_wala_point.x) + abs(prevy - sbse_left_wala_point.y);
                    ans+=max_x_at_level.get(e) - min_x_at_level.get(e);
                    ans+=max_y_at_level.get(e) - min_y_at_level.get(e);
                    prevx = sbse_niche_wala_point.x;
                    prevy = sbse_niche_wala_point.y;
                }
                else {
                    //pehle down phir up left
                    ans+=abs(prevx - sbse_niche_wala_point.x) + abs(prevy - sbse_niche_wala_point.y);
                    ans+=max_x_at_level.get(e) - min_x_at_level.get(e);
                    ans+=max_y_at_level.get(e) - min_y_at_level.get(e);
                    prevx = sbse_left_wala_point.x;
                    prevy = sbse_left_wala_point.y;
                }
        }
        pl(ans);
        pw.flush();
        pw.close();
    }
    static class Pair implements Comparable<Pair>
    {
        int x,y;
        Pair(int x,int y)
        {
            this.x=x;
            this.y=y;
        }
        public int compareTo(Pair other)
        {
            if(this.x!=other.x)
                return this.x-other.x;
            return this.y-other.y;
        }
        public String toString()
        {
            return "("+x+","+y+")";
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[64];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}

/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main
{
    static Reader scan;
    static PrintWriter pw;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<25)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static void solve() throws IOException
    {
        scan = new Reader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        int n = ni();
        TreeMap<Integer, Pair> leftmost = new TreeMap<>();
        TreeMap<Integer, Pair> downmost = new TreeMap<>();
        ArrayList<Integer> levels = new ArrayList<>();
        for(int i=0;i<n;++i) {
            int x = ni(), y = ni();
            int lev = max(x,y);
            if(!leftmost.containsKey(lev)) {
                leftmost.put(lev, new Pair(x,y));
                downmost.put(lev, new Pair(x,y));
            }
            else {
                Pair p = leftmost.get(lev);
                if(x<p.x) {
                    leftmost.put(lev, new Pair(x,y));
                }
                Pair q = downmost.get(lev);
                if(y<q.y) {
                    downmost.put(lev, new Pair(x,y));
                }
            }
        }
        //pl(downmost);
        //pl(leftmost);
        for(int e:leftmost.keySet()) {
            levels.add(e);
        }
        Collections.sort(levels);
        //pa("levels", levels);
        int N = levels.size();
        long dp[][] = new long[N][2];  //0 left, 1 down
        int highest_level = levels.get(N-1);
        dp[N-1][0] = dp[N-1][1] = dis(leftmost.get(highest_level), downmost.get(highest_level));
        for(int i=N-2;i>=0;--i) {
            int lev = levels.get(i);
            int nxtlev = levels.get(i+1);
            Pair foo = leftmost.get(lev);
            Pair bar = downmost.get(lev);
            long travel = dis(foo, bar);
            //pl("i : "+i+" travel : "+travel+" lev : "+lev);
            dp[i][0] = travel + min(dis(downmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1], dis(downmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0]);
            dp[i][1] = travel + min(dis(leftmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0], dis(leftmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1]);
        }
        //pa("DP", dp);
        long ans = min(dis(new Pair(0,0), leftmost.get(levels.get(0))) + dp[0][0], dis(new Pair(0,0), downmost.get(levels.get(0))) + dp[0][1]);
        pl(ans);
        pw.flush();
        pw.close();
    }
    static long dis(Pair p, Pair q) {
        return abs(p.x-q.x) + abs(p.y-q.y);
    }
    static class Pair implements Comparable<Pair>
    {
        int x,y;
        Pair(int x,int y)
        {
            this.x=x;
            this.y=y;
        }
        public int compareTo(Pair other)
        {
            if(this.x!=other.x)
                return this.x-other.x;
            return this.y-other.y;
        }
        public String toString()
        {
            return "("+x+","+y+")";
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[64];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}

/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main
{
    static Reader scan;
    static PrintWriter pw;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<25)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static void solve() throws IOException
    {
        scan = new Reader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        int n = ni();
        TreeMap<Integer, Pair> leftmost = new TreeMap<>();
        TreeMap<Integer, Pair> downmost = new TreeMap<>();
        ArrayList<Integer> levels = new ArrayList<>();
        for(int i=0;i<n;++i) {
            int x = ni(), y = ni();
            int lev = max(x,y);
            if(!leftmost.containsKey(lev)) {
                leftmost.put(lev, new Pair(x,y));
                downmost.put(lev, new Pair(x,y));
            }
            else {
                Pair p = leftmost.get(lev);
                if(x<p.x) {
                    leftmost.put(lev, new Pair(x,y));
                }
                Pair q = downmost.get(lev);
                if(y<q.y) {
                    downmost.put(lev, new Pair(x,y));
                }
            }
        }
        //pl(downmost);
        //pl(leftmost);
        for(int e:leftmost.keySet()) {
            levels.add(e);
        }
        //pa("levels", levels);
        int N = levels.size();
        long dp[][] = new long[N][2];  //0 left, 1 down
        int highest_level = levels.get(N-1);
        dp[N-1][0] = dp[N-1][1] = (highest_level - leftmost.get(highest_level).x) + (highest_level - downmost.get(highest_level).y);
        for(int i=N-2;i>=0;--i) {
            int lev = levels.get(i);
            int nxtlev = levels.get(i+1);
            Pair foo = leftmost.get(lev);
            Pair bar = downmost.get(lev);
            long travel = dis(foo, bar);
            //pl("i : "+i+" travel : "+travel+" lev : "+lev);
            dp[i][0] = travel + min(dis(downmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1], dis(downmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0]);
            dp[i][1] = travel + min(dis(leftmost.get(lev), leftmost.get(nxtlev)) + dp[i+1][0], dis(leftmost.get(lev), downmost.get(nxtlev)) + dp[i+1][1]);
        }
        //pa("DP", dp);
        long ans = min(dis(new Pair(0,0), leftmost.get(levels.get(0))) + dp[0][0], dis(new Pair(0,0), downmost.get(levels.get(0))) + dp[0][1]);
        pl(ans);
        pw.flush();
        pw.close();
    }
    static long dis(Pair p, Pair q) {
        return abs(p.x-q.x) + abs(p.y-q.y);
    }
    static class Pair implements Comparable<Pair>
    {
        int x,y;
        Pair(int x,int y)
        {
            this.x=x;
            this.y=y;
        }
        public int compareTo(Pair other)
        {
            if(this.x!=other.x)
                return this.x-other.x;
            return this.y-other.y;
        }
        public String toString()
        {
            return "("+x+","+y+")";
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[64];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}

import java.util.*;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int N = sc.nextInt();
    int[] x = new int[N];
    int[] y = new int[N];
    for (int i = 0; i < N; i++) {
      x[i] = sc.nextInt();
      y[i] = sc.nextInt();
    }
    int count = 0;
    int curX = 0;
    int curY = 0;
    HashSet<Integer> set = new HashSet<Integer>();
    for (int i = 0; i < N; i++) {
      int temp = Integer.MAX_VALUE;
      int index = -1;
      for (int j = 0; j < N; j++) {
        if (!set.contains(j) && (Math.abs(x[j] - curX) + Math.abs(y[j] - curY)) < temp) {
          index = j;
          temp = Math.abs(x[j] - curX) + Math.abs(y[j] - curY);
        }
      }
      curX = x[index];
      curY = y[index];
      count+= temp;
      set.add(index);
    }
    System.out.println(count);
  }
}

//package Contest515div3;

import java.io.PrintWriter;
import java.util.*;

public class mainF {
    public static Scanner enter = new Scanner(System.in);
    public static PrintWriter out = new PrintWriter(System.out);
    public static void main(String[] args) {
          int n=enter.nextInt();
          point mass[] =new point[n+1];
        for (int i = 0; i <n ; i++) {
            mass[i]=new point(enter.nextLong(),enter.nextLong());
        }
        mass[n]=new point((long)1e10,(long)1e10);
        Arrays.sort(mass,0,n);
        ArrayList<point> arrayList=new ArrayList<>(n);
        //arrayList.add(mass[0]);
        arrayList.add(new point(0,0));
        arrayList.add(new point(0,0));
        for (int i = 0; i <n ; i++) {
            if(Math.max(mass[i+1].x,mass[i+1].y)>Math.max(mass[i].x,mass[i].y)){
                if(i==0 || Math.max(mass[i-1].x,mass[i-1].y)<Math.max(mass[i].x,mass[i].y)){
                    arrayList.add(mass[i]);
                }
                arrayList.add(mass[i]);
                arrayList.add(mass[i+1]);
            }
        }

        long dp[]=new long[2*n];
        int last=0;
        for (int i = 2; i <arrayList.size()-1 ; i+=2) {
            dp[i]=Math.min(dist(arrayList.get(i+1),arrayList.get(i-1))+dp[i-1],dist(arrayList.get(i+1),arrayList.get(i-2))+dp[i-2])+dist(arrayList.get(i),arrayList.get(i+1));
            dp[i+1]=Math.min(dist(arrayList.get(i),arrayList.get(i-1))+dp[i-1],dist(arrayList.get(i),arrayList.get(i-2))+dp[i-2])+dist(arrayList.get(i),arrayList.get(i+1));
            last=i+1;
        }
        out.println(Math.min(dp[last],dp[last-1]));
        //System.out.println(arrayList);
        out.close();
       // System.out.println(Arrays.toString(mass));
    }

    public static long dist(point a,point b){
        return Math.abs(a.x-b.x)+Math.abs(a.y-b.y);

    }

}

class point implements Comparable<point>{
    long x,y;

    public point(long x, long y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public int compareTo(point o) {
        if(Math.max(x,y)<Math.max(o.x,o.y)) return -1;
        else if(Math.max(x,y)>Math.max(o.x,o.y)) return 1;
        else{
            if(x==o.x){
                return (y<=o.y)? -1: 1;
            }
            else if(y==o.y){
                return (x<=o.x)? -1: 1;
            }
        }
        return 0;
    }

    @Override
    public String toString() {
        return "("+x+", "+y+")";
    }
}

//package Contest515div3;

import java.io.PrintWriter;
import java.sql.SQLOutput;
import java.util.*;

public class mainF {
    public static Scanner enter = new Scanner(System.in);
    public static PrintWriter out = new PrintWriter(System.out);
    public static void main(String[] args) {
          int n=enter.nextInt();
          point mass[] =new point[n+1];
        for (int i = 0; i <n ; i++) {
            mass[i]=new point(enter.nextLong(),enter.nextLong());
        }
        mass[n]=new point((long)1e10,(long)1e10);
        Arrays.sort(mass,0,n);
        ArrayList<point> arrayList=new ArrayList<>(n);
        //arrayList.add(mass[0]);
        arrayList.add(new point(0,0));
        arrayList.add(new point(0,0));

       // System.out.println(Arrays.toString(mass));
        for (int i = 0; i <n ; i++) {
            if(Math.max(mass[i+1].x,mass[i+1].y)>Math.max(mass[i].x,mass[i].y)){
                if(i==0){
                    arrayList.add(mass[i]);
                }
                arrayList.add(mass[i]);
                arrayList.add(mass[i+1]);
            }
        }

        //arrayList.remove(arrayList.size()-1);
        //System.out.println(arrayList);
        long dp[]=new long[(int)1e6];
        int last=0;
        for (int i = 2; i <arrayList.size()-1 ; i+=2) {
            dp[i]=Math.min(dist(arrayList.get(i+1),arrayList.get(i-1))+dp[i-1],dist(arrayList.get(i+1),arrayList.get(i-2))+dp[i-2])+dist(arrayList.get(i),arrayList.get(i+1));
            dp[i+1]=Math.min(dist(arrayList.get(i),arrayList.get(i-1))+dp[i-1],dist(arrayList.get(i),arrayList.get(i-2))+dp[i-2])+dist(arrayList.get(i),arrayList.get(i+1));
            last=i+1;
        }
        out.println(Math.min(dp[last],dp[last-1]));
        out.close();
    }

    public static long dist(point a,point b){
        return Math.abs(a.x-b.x)+Math.abs(a.y-b.y);

    }

}

class point implements Comparable<point>{
    long x,y;

    public point(long x, long y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public int compareTo(point o) {
        if(Math.max(x,y)<Math.max(o.x,o.y)) return -1;
        else if(Math.max(x,y)>Math.max(o.x,o.y)) return 1;
        else{
             if(y==o.y){
                return (x<=o.x)? -1: 1;
            }
            else if(x==o.x){
                 return (y>=o.y)? -1: 1;
             }
             else{
                 return (x<=o.x)? -1: 1;
             }
        }
    }

    @Override
    public String toString() {
        return "("+x+", "+y+")";
    }
}

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import static java.lang.Math.*;

/* spar5h */

public class cf6{

	static int[] left, down, val;
	static long[][] dp;

	static void recur(int i, int d, int m, int x, int y) {

		if(i == m) {
			 dp[i][d] = 0; return;
		}

		dp[i][d] = Long.MAX_VALUE;

		int x1, y1;

		if(left[i + 1] != -1) {
			x1 = left[i + 1]; y1 = val[i + 1];
		}
		else {
			x1 = val[i + 1]; y1 = down[i + 1];
		}

		int x2, y2;

		if(down[i + 1] != -1) {
			x2 = val[i + 1]; y2 = down[i + 1];
		}
		else {
			x2 = left[i + 1]; y2 = val[i + 1];
		}

		long dist = abs(x1 - x2) + abs(y1 - y2);

		if(dp[i + 1][0] == -1)
			recur(i + 1, 0, m, x2, y2);

		dp[i][d] = min(dp[i + 1][0] + abs(x - x1) + abs(y - y1) + dist, dp[i][d]);

		if(dp[i + 1][1] == -1)
			recur(i + 1, 1, m, x1, y1);

		dp[i][d] = min(dp[i + 1][1] + abs(x - x2) + abs(y - y2) + dist, dp[i][d]);
	}

	public static void main(String[] args) {

		InputReader s = new InputReader(System.in);
		PrintWriter w = new PrintWriter(System.out);

		int n = s.nextInt();

		int[] x = new int[n];
		int[] y = new int[n];

		TreeSet<Integer> ts = new TreeSet<Integer>();

		for(int i = 0; i < n; i++) {

			x[i] = s.nextInt();
			y[i] = s.nextInt();

			ts.add(max(x[i], y[i]));
		}

		int m = 0;
		val = new int[ts.size() + 1];

		HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
		hm.put(0, 0);

		for(int i : ts) {
			m = m + 1; val[m] = i; hm.put(i, m);
		}

		left = new int[m + 1];
		Arrays.fill(left, -1);

		down = new int[m + 1];
		Arrays.fill(down, -1);

		for(int i = 0; i < n; i++) {

			int j = hm.get(max(x[i], y[i]));

			if(x[i] == max(x[i], y[i])) {

				if(down[j] == -1 || y[i] < down[j])
					down[j] = y[i];
			}

			else {

				if(left[j] == -1 || x[i] < left[j])
					left[j] = x[i];
			}
		}

		dp = new long[m + 1][2];

		for(int i = 0; i <= m; i++)
			for(int j = 0; j < 2; j++)
				dp[i][j] = -1;

		recur(0, 0, m, 0, 0);

		w.println(dp[0][0]);

		w.close();
	}

	static class InputReader {

		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream)
		{
			this.stream = stream;
		}

		public int read()
		{
			if (numChars==-1)
				throw new InputMismatchException();

			if (curChar >= numChars)
			{
				curChar = 0;
				try
				{
					numChars = stream.read(buf);
				}
				catch (IOException e)
				{
					throw new InputMismatchException();
				}

				if(numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public String nextLine()
		{
			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
		}
		public int nextInt()
		{
			int c = read();

			while(isSpaceChar(c))
				c = read();

			int sgn = 1;

			if (c == '-')
			{
				sgn = -1;
				c = read();
			}

			int res = 0;
			do
			{
				if(c<'0'||c>'9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));

			return res * sgn;
		}

		public long nextLong()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			long res = 0;

			do
			{
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));
				return res * sgn;
		}

		public double nextDouble()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			double res = 0;
			while (!isSpaceChar(c) && c != '.')
			{
				if (c == 'e' || c == 'E')
					return res * Math.pow(10, nextInt());
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			if (c == '.')
			{
				c = read();
				double m = 1;
				while (!isSpaceChar(c))
				{
					if (c == 'e' || c == 'E')
						return res * Math.pow(10, nextInt());
					if (c < '0' || c > '9')
						throw new InputMismatchException();
					m /= 10;
					res += (c - '0') * m;
					c = read();
				}
			}
			return res * sgn;
		}

		public String readString()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do
			{
				res.appendCodePoint(c);
				c = read();
			}
			while (!isSpaceChar(c));

			return res.toString();
		}

		public boolean isSpaceChar(int c)
		{
			if (filter != null)
				return filter.isSpaceChar(c);
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public String next()
		{
			return readString();
		}

		public interface SpaceCharFilter
		{
			public boolean isSpaceChar(int ch);
		}
	}

}

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import static java.lang.Math.*;

/* spar5h */

public class cf6{

	static int[] left, down, val;
	static long[][] dp;

	static void recur(int i, int d, int m, int x, int y) {

		if(i == m) {
			 dp[i][d] = 0; return;
		}

		dp[i][d] = Long.MAX_VALUE;

		int x1, y1;

		if(left[i + 1] != -1) {
			x1 = left[i + 1]; y1 = val[i + 1];
		}
		else {
			x1 = val[i + 1]; y1 = down[i + 1];
		}

		int x2, y2;

		if(down[i + 1] != -1) {
			x2 = val[i + 1]; y2 = down[i + 1];
		}
		else {
			x2 = left[i + 1]; y2 = down[i + 1];
		}

		int dist = abs(x1 - x2) + abs(y1 - y2);

		if(dp[i + 1][0] == -1)
			recur(i + 1, 0, m, x2, y2);

		dp[i][d] = min(abs(x - x1) + abs(y - y1) + dist + dp[i + 1][0], dp[i][d]);

		if(dp[i + 1][1] == -1)
			recur(i + 1, 1, m, x1, y1);

		dp[i][d] = min(abs(x - x2) + abs(y - y2) + dist + dp[i + 1][1], dp[i][d]);
	}

	public static void main(String[] args) {

		InputReader s = new InputReader(System.in);
		PrintWriter w = new PrintWriter(System.out);

		int n = s.nextInt();

		int[] x = new int[n];
		int[] y = new int[n];

		TreeSet<Integer> ts = new TreeSet<Integer>();

		for(int i = 0; i < n; i++) {

			x[i] = s.nextInt();
			y[i] = s.nextInt();

			ts.add(max(x[i], y[i]));
		}

		int m = 0;
		val = new int[ts.size() + 1];

		HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
		hm.put(0, 0);

		for(int i : ts) {
			m = m + 1; val[m] = i; hm.put(i, m);
		}

		left = new int[m + 1];
		Arrays.fill(left, -1);

		down = new int[m + 1];
		Arrays.fill(down, -1);

		for(int i = 0; i < n; i++) {

			int j = hm.get(max(x[i], y[i]));

			if(x[i] == max(x[i], y[i])) {

				if(down[j] == -1 || y[i] < down[j])
					down[j] = y[i];
			}

			else {

				if(left[j] == -1 || x[i] < left[j])
					left[j] = x[i];
			}
		}

		dp = new long[m + 1][2];

		for(int i = 0; i <= m; i++)
			for(int j = 0; j < 2; j++)
				dp[i][j] = -1;

		recur(0, 0, m, 0, 0);

		w.println(dp[0][0]);

		w.close();
	}

	static class InputReader {

		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream)
		{
			this.stream = stream;
		}

		public int read()
		{
			if (numChars==-1)
				throw new InputMismatchException();

			if (curChar >= numChars)
			{
				curChar = 0;
				try
				{
					numChars = stream.read(buf);
				}
				catch (IOException e)
				{
					throw new InputMismatchException();
				}

				if(numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public String nextLine()
		{
			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
		}
		public int nextInt()
		{
			int c = read();

			while(isSpaceChar(c))
				c = read();

			int sgn = 1;

			if (c == '-')
			{
				sgn = -1;
				c = read();
			}

			int res = 0;
			do
			{
				if(c<'0'||c>'9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));

			return res * sgn;
		}

		public long nextLong()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			long res = 0;

			do
			{
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));
				return res * sgn;
		}

		public double nextDouble()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			double res = 0;
			while (!isSpaceChar(c) && c != '.')
			{
				if (c == 'e' || c == 'E')
					return res * Math.pow(10, nextInt());
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			if (c == '.')
			{
				c = read();
				double m = 1;
				while (!isSpaceChar(c))
				{
					if (c == 'e' || c == 'E')
						return res * Math.pow(10, nextInt());
					if (c < '0' || c > '9')
						throw new InputMismatchException();
					m /= 10;
					res += (c - '0') * m;
					c = read();
				}
			}
			return res * sgn;
		}

		public String readString()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do
			{
				res.appendCodePoint(c);
				c = read();
			}
			while (!isSpaceChar(c));

			return res.toString();
		}

		public boolean isSpaceChar(int c)
		{
			if (filter != null)
				return filter.isSpaceChar(c);
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public String next()
		{
			return readString();
		}

		public interface SpaceCharFilter
		{
			public boolean isSpaceChar(int ch);
		}
	}

}

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import static java.lang.Math.*;

/* spar5h */

public class cf6{

	static int[] left, down, val;
	static long[][] dp;

	static void recur(int i, int d, int m, int x, int y) {

		if(i == m) {
			 dp[i][d] = 0; return;
		}

		dp[i][d] = Long.MAX_VALUE;

		int x1, y1;

		if(left[i + 1] != -1) {
			x1 = left[i + 1]; y1 = val[i + 1];
		}
		else {
			x1 = val[i + 1]; y1 = down[i + 1];
		}

		int x2, y2;

		if(down[i + 1] != -1) {
			x2 = val[i + 1]; y2 = down[i + 1];
		}
		else {
			x2 = left[i + 1]; y2 = val[i + 1];
		}

		long dist = abs(x1 - x2) + abs(y1 - y2);

		if(dp[i + 1][0] == -1)
			recur(i + 1, 0, m, x2, y2);

		dp[i][d] = min(dp[i + 1][0] + abs(x - x1) + abs(y - y1) + dist, dp[i][d]);

		if(dp[i + 1][1] == -1)
			recur(i + 1, 1, m, x1, y1);

		dp[i][d] = min(dp[i + 1][1] + abs(x - x2) + abs(y - y2) + dist, dp[i][d]);
	}

	public static void main(String[] args) {

		InputReader s = new InputReader(System.in);
		PrintWriter w = new PrintWriter(System.out);

		int n = s.nextInt();

		int[] x = new int[n];
		int[] y = new int[n];

		TreeSet<Integer> ts = new TreeSet<Integer>();

		for(int i = 0; i < n; i++) {

			x[i] = s.nextInt();
			y[i] = s.nextInt();

			ts.add(max(x[i], y[i]));
		}

		int m = 0;
		val = new int[ts.size() + 1];

		HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
		hm.put(0, 0);

		for(int i : ts) {
			m = m + 1; val[m] = i; hm.put(i, m);
		}

		left = new int[m + 1];
		Arrays.fill(left, -1); left[0] = 0;

		down = new int[m + 1];
		Arrays.fill(down, -1); down[0] = 0;

		for(int i = 0; i < n; i++) {

			int j = hm.get(max(x[i], y[i]));

			if(x[i] == max(x[i], y[i])) {

				if(down[j] == -1 || y[i] < down[j])
					down[j] = y[i];
			}

			else {

				if(left[j] == -1 || x[i] < left[j])
					left[j] = x[i];
			}
		}

		dp = new long[m + 1][2];

		for(int i = 0; i <= m; i++)
			for(int j = 0; j < 2; j++)
				dp[i][j] = -1;

		recur(0, 0, m, 0, 0);

		w.println(dp[0][0]);

		w.close();
	}

	static class InputReader {

		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream)
		{
			this.stream = stream;
		}

		public int read()
		{
			if (numChars==-1)
				throw new InputMismatchException();

			if (curChar >= numChars)
			{
				curChar = 0;
				try
				{
					numChars = stream.read(buf);
				}
				catch (IOException e)
				{
					throw new InputMismatchException();
				}

				if(numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public String nextLine()
		{
			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
		}
		public int nextInt()
		{
			int c = read();

			while(isSpaceChar(c))
				c = read();

			int sgn = 1;

			if (c == '-')
			{
				sgn = -1;
				c = read();
			}

			int res = 0;
			do
			{
				if(c<'0'||c>'9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));

			return res * sgn;
		}

		public long nextLong()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			long res = 0;

			do
			{
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));
				return res * sgn;
		}

		public double nextDouble()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-')
			{
				sgn = -1;
				c = read();
			}
			double res = 0;
			while (!isSpaceChar(c) && c != '.')
			{
				if (c == 'e' || c == 'E')
					return res * Math.pow(10, nextInt());
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			if (c == '.')
			{
				c = read();
				double m = 1;
				while (!isSpaceChar(c))
				{
					if (c == 'e' || c == 'E')
						return res * Math.pow(10, nextInt());
					if (c < '0' || c > '9')
						throw new InputMismatchException();
					m /= 10;
					res += (c - '0') * m;
					c = read();
				}
			}
			return res * sgn;
		}

		public String readString()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do
			{
				res.appendCodePoint(c);
				c = read();
			}
			while (!isSpaceChar(c));

			return res.toString();
		}

		public boolean isSpaceChar(int c)
		{
			if (filter != null)
				return filter.isSpaceChar(c);
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public String next()
		{
			return readString();
		}

		public interface SpaceCharFilter
		{
			public boolean isSpaceChar(int ch);
		}
	}

}

import java.io.*;
import java.util.*;

public class Main {

    public static void main(String[] args) throws Exception {

        new Main().go();
    }

    PrintWriter out;
    Reader in;
    BufferedReader br;

    Main() throws IOException {

        try {

            //br = new BufferedReader( new FileReader("input.txt") );
            //in = new Reader("input.txt");
            in = new Reader("input.txt");
            out = new PrintWriter( new BufferedWriter(new FileWriter("output.txt")) );
        }
        catch (Exception e) {

            //br = new BufferedReader( new InputStreamReader( System.in ) );
            in = new Reader();
            out = new PrintWriter( new BufferedWriter(new OutputStreamWriter(System.out)) );
        }
    }

    void go() throws Exception {

        //int t = in.nextInt();
        int cs = 1;
        int t = 1;
        while (t > 0) {
            //out.print("Case #" + cs + ": ");
            solve();
            t--;
            cs++;
        }

        out.flush();
        out.close();
    }

    int inf = 2000000000;
    int mod = 1000000007;
    double eps = 0.000000001;

    int n;
    int m;

    ArrayList<Pair>[] g;
    void solve() throws IOException {

        int n = in.nextInt();

        TreeMap<Integer, Pair> map = new TreeMap<>();

        Pair[] points = new Pair[n];
        for (int i = 0; i < n; i++) {
            int x = in.nextInt();
            int y = in.nextInt();
            int lev = Math.max(x, y);
            points[i] = new Pair(x, y);
            if (!map.containsKey(lev)) {
                map.put(lev, new Pair(i, i));
            } else {
                Pair p1 = points[map.get(lev).a];
                Pair p2 = points[map.get(lev).b];
                if (y == lev && (p1.b != y || p1.a > x)) {
                    map.get(lev).a = i;
                } else if (x == lev && (p2.a != x || p2.b > y)) {
                    map.get(lev).b = i;
                }
            }
        }

        int levs = map.keySet().size();
        long[][] dp = new long[2][levs + 1];
        long ans = 0;
        int pos = 1;
        Pair prev1 = new Pair(0, 0);
        Pair prev2 = new Pair(0, 0);
        for (int k : map.keySet()) {
            Pair p1 = points[map.get(k).a];
            Pair p2 = points[map.get(k).b];
            ans += (p1.b - p2.b) + (p2.a - p1.a);

            dp[0][pos] = Math.min(
                    dp[0][pos - 1] + dist(p2, prev1),
                    dp[1][pos - 1] + dist(p2, prev2));

            dp[1][pos] = Math.min(
                    dp[0][pos - 1] + dist(p1, prev1),
                    dp[1][pos - 1] + dist(p1, prev2));

            prev1 = p1;
            prev2 = p2;
            pos++;
            //System.err.println(k);
            //System.err.println(p1.a + " " + p1.b);
            //System.err.println(p2.a + " " + p2.b);
        }

        ans += Math.min(dp[0][levs], dp[1][levs]);
        out.println(ans);
    }

    int dist(Pair p1, Pair p2) {
        return Math.abs(p1.a - p2.a) + Math.abs(p1.b - p2.b);
    }

    class Pair implements Comparable<Pair>{

        int a;
        int b;

        Pair(int a, int b) {

            this.a = a;
            this.b = b;
        }

        public int compareTo(Pair p) {
            if (a != p.a)
                return Integer.compare(a, p.a);
            else
                return Integer.compare(b, p.b);
        }
    }

    class Item {

        int a;
        int b;
        int c;

        Item(int a, int b, int c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }

    }

    class Reader {

        BufferedReader  br;
        StringTokenizer tok;

        Reader(String file) throws IOException {
            br = new BufferedReader( new FileReader(file) );
        }

        Reader() throws IOException {
            br = new BufferedReader( new InputStreamReader(System.in) );
        }

        String next() throws IOException {

            while (tok == null || !tok.hasMoreElements())
                tok = new StringTokenizer(br.readLine());
            return tok.nextToken();
        }

        int nextInt() throws NumberFormatException, IOException {
            return Integer.valueOf(next());
        }

        long nextLong() throws NumberFormatException, IOException {
            return Long.valueOf(next());
        }

        double nextDouble() throws NumberFormatException, IOException {
            return Double.valueOf(next());
        }

        String nextLine() throws IOException {
            return br.readLine();
        }

    }

    static class InputReader
    {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public InputReader()
        {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public InputReader(String file_name) throws IOException
        {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException
        {
            byte[] buf = new byte[64]; // line length
            int cnt = 0, c;
            while ((c = read()) != -1)
            {
                if (c == '\n')
                    break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException
        {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do
            {
                ret = ret * 10 + c - '0';
            }  while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        public long nextLong() throws IOException
        {
            long ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');
            if (neg)
                return -ret;
            return ret;
        }

        public double nextDouble() throws IOException
        {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();

            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');

            if (c == '.')
            {
                while ((c = read()) >= '0' && c <= '9')
                {
                    ret += (c - '0') / (div *= 10);
                }
            }

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException
        {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1)
                buffer[0] = -1;
        }

        private byte read() throws IOException
        {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException
        {
            if (din == null)
                return;
            din.close();
        }
    }

}

import java.io.*;
import java.util.*;

public class Main {

    public static void main(String[] args) throws Exception {

        new Main().go();
    }

    PrintWriter out;
    Reader in;
    BufferedReader br;

    Main() throws IOException {

        try {

            //br = new BufferedReader( new FileReader("input.txt") );
            //in = new Reader("input.txt");
            in = new Reader("input.txt");
            out = new PrintWriter( new BufferedWriter(new FileWriter("output.txt")) );
        }
        catch (Exception e) {

            //br = new BufferedReader( new InputStreamReader( System.in ) );
            in = new Reader();
            out = new PrintWriter( new BufferedWriter(new OutputStreamWriter(System.out)) );
        }
    }

    void go() throws Exception {

        //int t = in.nextInt();
        int cs = 1;
        int t = 1;
        while (t > 0) {
            //out.print("Case #" + cs + ": ");
            solve();
            t--;
            cs++;
        }

        out.flush();
        out.close();
    }

    int inf = 2000000000;
    int mod = 1000000007;
    double eps = 0.000000001;

    int n;
    int m;

    ArrayList<Pair>[] g;
    void solve() throws IOException {

        int n = in.nextInt();

        TreeMap<Integer, Pair> map = new TreeMap<>();

        Pair[] points = new Pair[n];
        for (int i = 0; i < n; i++) {
            int x = in.nextInt();
            int y = in.nextInt();
            int lev = Math.max(x, y);
            points[i] = new Pair(x, y);
            if (!map.containsKey(lev)) {
                map.put(lev, new Pair(i, i));
            } else {
                Pair p1 = points[map.get(lev).a];
                Pair p2 = points[map.get(lev).b];
                if (y == lev && (p1.b != y || p1.a > x)) {
                    map.get(lev).a = i;
                }

                if (x == lev && (p2.a != x || p2.b > y)) {
                    map.get(lev).b = i;
                }
            }
        }

        int levs = map.keySet().size();
        long[][] dp = new long[2][levs + 1];
        long ans = 0;
        int pos = 1;
        Pair prev1 = new Pair(0, 0);
        Pair prev2 = new Pair(0, 0);
        for (int k : map.keySet()) {
            Pair p1 = points[map.get(k).a];
            Pair p2 = points[map.get(k).b];
            ans += dist(p1, p2);

            dp[0][pos] = Math.min(
                    dp[0][pos - 1] + dist(p2, prev1),
                    dp[1][pos - 1] + dist(p2, prev2));

            dp[1][pos] = Math.min(
                    dp[0][pos - 1] + dist(p1, prev1),
                    dp[1][pos - 1] + dist(p1, prev2));

            prev1 = p1;
            prev2 = p2;
            pos++;
            //System.err.println(k);
            //System.err.println(p1.a + " " + p1.b);
            //System.err.println(p2.a + " " + p2.b);
        }

        ans += Math.min(dp[0][levs], dp[1][levs]);
        out.println(ans);
    }

    int dist(Pair p1, Pair p2) {
        return Math.abs(p1.a - p2.a) + Math.abs(p1.b - p2.b);
    }

    class Pair implements Comparable<Pair>{

        int a;
        int b;

        Pair(int a, int b) {

            this.a = a;
            this.b = b;
        }

        public int compareTo(Pair p) {
            if (a != p.a)
                return Integer.compare(a, p.a);
            else
                return Integer.compare(b, p.b);
        }
    }

    class Item {

        int a;
        int b;
        int c;

        Item(int a, int b, int c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }

    }

    class Reader {

        BufferedReader  br;
        StringTokenizer tok;

        Reader(String file) throws IOException {
            br = new BufferedReader( new FileReader(file) );
        }

        Reader() throws IOException {
            br = new BufferedReader( new InputStreamReader(System.in) );
        }

        String next() throws IOException {

            while (tok == null || !tok.hasMoreElements())
                tok = new StringTokenizer(br.readLine());
            return tok.nextToken();
        }

        int nextInt() throws NumberFormatException, IOException {
            return Integer.valueOf(next());
        }

        long nextLong() throws NumberFormatException, IOException {
            return Long.valueOf(next());
        }

        double nextDouble() throws NumberFormatException, IOException {
            return Double.valueOf(next());
        }

        String nextLine() throws IOException {
            return br.readLine();
        }

    }

    static class InputReader
    {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public InputReader()
        {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public InputReader(String file_name) throws IOException
        {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException
        {
            byte[] buf = new byte[64]; // line length
            int cnt = 0, c;
            while ((c = read()) != -1)
            {
                if (c == '\n')
                    break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException
        {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do
            {
                ret = ret * 10 + c - '0';
            }  while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        public long nextLong() throws IOException
        {
            long ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');
            if (neg)
                return -ret;
            return ret;
        }

        public double nextDouble() throws IOException
        {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();

            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');

            if (c == '.')
            {
                while ((c = read()) >= '0' && c <= '9')
                {
                    ret += (c - '0') / (div *= 10);
                }
            }

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException
        {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1)
                buffer[0] = -1;
        }

        private byte read() throws IOException
        {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException
        {
            if (din == null)
                return;
            din.close();
        }
    }

}

import java.io.*;
import java.math.*;
import java.util.*;
import java.awt.Point;

public class Main {
	static final long MOD = 998244353L;
	//static final long INF = -1000000000000000007L;
	//static final long MOD = 1000000007L;
	//static final int INF = 1000000007;

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		PrintWriter pw = new PrintWriter(System.out);
		int N = sc.ni();
		int[][] points = new int[N+1][2];
		for (int i = 1; i <= N; i++) {
			points[i] = new int[]{sc.ni(),sc.ni()};
		}
		points = sortPoints(points);

		int[] rungs = new int[N+1];
		for (int i = 0; i <= N; i++) {
			rungs[i] = Math.max(points[i][0],points[i][1]);
		}
		long[][] dp = new long[N+5][2];
		//dp[i][0] represents leaving the rung at the left most point
		//dp[i][1] represents leaving the run at the right most point
		int[] left = {0,0};
		int[] right = {0,0};
		int i = 0;
		int index = 1;
		while (i <= N) {
			int j = i;
			int[] newLeft = points[i];
			while (j <= N && rungs[j] == rungs[i]) {
				j++;
			}
			int[] newRight = points[j-1];

			long distLR = dist(newLeft,newRight);

			dp[index][0] = distLR+Math.min(dp[index-1][0]+dist(left,newRight),dp[index-1][1]+dist(right,newRight));
			dp[index][1] = distLR+Math.min(dp[index-1][0]+dist(left,newLeft),dp[index-1][1]+dist(right,newLeft));
			left = newLeft;
			right = newRight;
			index++;
			i = j;
		}

		pw.println(Math.min(dp[index-1][0],dp[index-1][0]));
		pw.close();
 	}

	public static long dist(int[] p, int[] q) {
		return (long)(Math.abs(p[0]-q[0])+Math.abs(p[1]-q[1]));
	}

    public static int[][] sortPoints(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  if (Math.max(arr1[0],arr1[1]) != Math.max(arr2[0],arr2[1])) {
					  return Math.max(arr1[0],arr1[1]) - Math.max(arr2[0],arr2[1]);
				  } else if (arr1[0] != arr2[0]) {
					  return arr2[0]-arr1[0];
				  } else {
					  return arr1[1]-arr2[1];
				  }
	          }
		});
		return array;
	}

    public static int[][] sort(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  return arr1[0]-arr2[0]; //ascending order
	          }
		});
		return array;
	}

    public static long[][] sort(long[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    long[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<long[]>() {
			  @Override
			  //Descending order
        	  public int compare(long[] arr1, long[] arr2) {
				  if (arr2[0] < arr1[0])
					  return -1;
				  if (arr2[0] > arr1[0])
					  return 1;
				  return 0;
	          }
		});
		return array;
	}

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int ni() {
            return Integer.parseInt(next());
        }

        long nl() {
            return Long.parseLong(next());
        }

        double nd() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.math.*;
import java.util.*;
import java.awt.Point;

public class Main {
	static final long MOD = 998244353L;
	//static final long INF = -1000000000000000007L;
	//static final long MOD = 1000000007L;
	//static final int INF = 1000000007;

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		PrintWriter pw = new PrintWriter(System.out);
		int N = sc.ni();
		int[][] points = new int[N+1][2];
		for (int i = 1; i <= N; i++) {
			points[i] = new int[]{sc.ni(),sc.ni()};
		}
		points = sortPoints(points);

		int[] rungs = new int[N+1];
		for (int i = 0; i <= N; i++) {
			rungs[i] = Math.max(points[i][0],points[i][1]);
		}
		long[][] dp = new long[N+5][2];
		//dp[i][0] represents leaving the rung at the left most point
		//dp[i][1] represents leaving the run at the right most point
		int[] left = {0,0};
		int[] right = {0,0};
		int i = 0;
		int index = 1;
		while (i <= N) {
			int j = i;
			int[] newLeft = points[i];
			while (j <= N && rungs[j] == rungs[i]) {
				j++;
			}
			int[] newRight = points[j-1];

			long distLR = dist(newLeft,newRight);

			dp[index][0] = distLR+Math.min(dp[index-1][0]+dist(left,newRight),dp[index-1][1]+dist(right,newRight));
			dp[index][1] = distLR+Math.min(dp[index-1][0]+dist(left,newLeft),dp[index-1][1]+dist(right,newLeft));
			left = newLeft;
			right = newRight;
			index++;
			i = j;
		}

		pw.println(Math.min(dp[index-1][0],dp[index-1][0]));
		pw.close();
 	}

	public static long dist(int[] p, int[] q) {
		return (long)(Math.abs(p[0]-q[0])+Math.abs(p[1]-q[1]));
	}

    public static int[][] sortPoints(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  if (Math.max(arr1[0],arr1[1]) != Math.max(arr2[0],arr2[1])) {
					  return Math.max(arr1[0],arr1[1]) - Math.max(arr2[0],arr2[1]);
				  } else if (arr1[0] != arr2[0]) {
					  return arr1[0]-arr2[0];
				  } else {
					  return arr1[1]-arr2[1];
				  }
	          }
		});
		return array;
	}

    public static int[][] sort(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  return arr1[0]-arr2[0]; //ascending order
	          }
		});
		return array;
	}

    public static long[][] sort(long[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    long[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<long[]>() {
			  @Override
			  //Descending order
        	  public int compare(long[] arr1, long[] arr2) {
				  if (arr2[0] < arr1[0])
					  return -1;
				  if (arr2[0] > arr1[0])
					  return 1;
				  return 0;
	          }
		});
		return array;
	}

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int ni() {
            return Integer.parseInt(next());
        }

        long nl() {
            return Long.parseLong(next());
        }

        double nd() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.math.*;
import java.util.*;
import java.awt.Point;

public class Main {
	static final long MOD = 998244353L;
	//static final long INF = -1000000000000000007L;
	//static final long MOD = 1000000007L;
	//static final int INF = 1000000007;

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		PrintWriter pw = new PrintWriter(System.out);
		int N = sc.ni();
		int[][] points = new int[N+1][2];
		for (int i = 1; i <= N; i++) {
			points[i] = new int[]{sc.ni(),sc.ni()};
		}
		points = sortPoints(points);

		int[] rungs = new int[N+1];
		for (int i = 0; i <= N; i++) {
			rungs[i] = Math.max(points[i][0],points[i][1]);
		}
		long[][] dp = new long[N+5][2];
		//dp[i][0] represents leaving the rung at the left most point
		//dp[i][1] represents leaving the run at the right most point
		int[] left = {0,0};
		int[] right = {0,0};
		int i = 0;
		int index = 1;
		while (i <= N) {
			int j = i;
			int[] newLeft = points[i];
			while (j <= N && rungs[j] == rungs[i]) {
				j++;
			}
			int[] newRight = points[j-1];

			long distLR = dist(newLeft,newRight);

			dp[index][0] = distLR+Math.min(dp[index-1][0]+dist(left,newRight),dp[index-1][1]+dist(right,newRight));
			dp[index][1] = distLR+Math.min(dp[index-1][0]+dist(left,newLeft),dp[index-1][1]+dist(right,newLeft));
			left = newLeft;
			right = newRight;
			index++;
			i = j;
		}

		pw.println(Math.min(dp[index-1][0],dp[index-1][0]));
		pw.close();
 	}

	public static long dist(int[] p, int[] q) {
		return (long)(Math.abs(p[0]-q[0])+Math.abs(p[1]-q[1]));
	}

    public static int[][] sortPoints(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  if (Math.max(arr1[0],arr1[1]) != Math.max(arr2[0],arr2[1])) {
					  return Math.max(arr1[0],arr1[1]) - Math.max(arr2[0],arr2[1]);
				  } else {
					  int[] leftMost = {0,Math.max(arr1[0],arr1[1])};
					  return (int)(dist(leftMost,arr1)-dist(leftMost,arr2));
				  }
	          }
		});
		return array;
	}

    public static int[][] sort(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  return arr1[0]-arr2[0]; //ascending order
	          }
		});
		return array;
	}

    public static long[][] sort(long[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    long[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<long[]>() {
			  @Override
			  //Descending order
        	  public int compare(long[] arr1, long[] arr2) {
				  if (arr2[0] < arr1[0])
					  return -1;
				  if (arr2[0] > arr1[0])
					  return 1;
				  return 0;
	          }
		});
		return array;
	}

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int ni() {
            return Integer.parseInt(next());
        }

        long nl() {
            return Long.parseLong(next());
        }

        double nd() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.math.*;
import java.util.*;
import java.awt.Point;

public class Main {
	static final long MOD = 998244353L;
	//static final long INF = -1000000000000000007L;
	//static final long MOD = 1000000007L;
	//static final int INF = 1000000007;

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		PrintWriter pw = new PrintWriter(System.out);
		int N = sc.ni();
		int[][] points = new int[N+1][2];
		for (int i = 1; i <= N; i++) {
			points[i] = new int[]{sc.ni(),sc.ni()};
		}
		points = sortPoints(points);

		int[] rungs = new int[N+1];
		for (int i = 0; i <= N; i++) {
			rungs[i] = Math.max(points[i][0],points[i][1]);
		}
		long[][] dp = new long[N+5][2];
		//dp[i][0] represents leaving the rung at the left most point
		//dp[i][1] represents leaving the run at the right most point
		int[] left = {0,0};
		int[] right = {0,0};
		int i = 0;
		int index = 1;
		while (i <= N) {
			int j = i;
			int[] newLeft = points[i];
			while (j <= N && rungs[j] == rungs[i]) {
				j++;
			}
			int[] newRight = points[j-1];

			long distLR = dist(newLeft,newRight);

			dp[index][0] = distLR+Math.min(dp[index-1][0]+dist(left,newRight),dp[index-1][1]+dist(right,newRight));
			dp[index][1] = distLR+Math.min(dp[index-1][0]+dist(left,newLeft),dp[index-1][1]+dist(right,newLeft));
			left = newLeft;
			right = newRight;
			index++;
			i = j;
		}

		pw.println(Math.min(dp[index-1][0],dp[index-1][0]));
		pw.close();
 	}

	public static long dist(int[] p, int[] q) {
		return (long)(Math.abs(p[0]-q[0])+Math.abs(p[1]-q[1]));
	}

    public static int[][] sortPoints(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  if (Math.max(arr1[0],arr1[1]) != Math.max(arr2[0],arr2[1])) {
					  return Math.max(arr1[0],arr1[1]) - Math.max(arr2[0],arr2[1]);
				  } else if (arr1[0] != arr2[0]) {
					  return arr1[0]-arr2[0];
				  } else {
					  return arr2[1]-arr1[1];
				  }
	          }
		});
		return array;
	}

    public static int[][] sort(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  return arr1[0]-arr2[0]; //ascending order
	          }
		});
		return array;
	}

    public static long[][] sort(long[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    long[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<long[]>() {
			  @Override
			  //Descending order
        	  public int compare(long[] arr1, long[] arr2) {
				  if (arr2[0] < arr1[0])
					  return -1;
				  if (arr2[0] > arr1[0])
					  return 1;
				  return 0;
	          }
		});
		return array;
	}

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int ni() {
            return Integer.parseInt(next());
        }

        long nl() {
            return Long.parseLong(next());
        }

        double nd() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.util.*;

public class YetAnother2DWalking {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver solver = new Solver();
        solver.solve(inp, out);
        out.close();
    }

    static class Solver {
        private void solve(InputReader inp, PrintWriter out) {
            int n = inp.nextInt();
            HashMap<Integer, Coord> left = new HashMap<>();
            HashMap<Integer, Coord> right = new HashMap<>();
            Set<Integer> temp = new HashSet<>();
            for (int i = 0; i < n; i++) {
                int x = inp.nextInt();
                int y = inp.nextInt();
                int layer = Math.max(x, y);
                temp.add(layer);
                Coord l = left.getOrDefault(layer, null);
                Coord r = right.getOrDefault(layer, null);
                if (l == null || x < l.x || y > l.y) left.put(layer, new Coord(x, y));
                if (r == null || x > l.x || y < l.y) right.put(layer, new Coord(x, y));
            }
            ArrayList<Integer> layers = new ArrayList<>(temp);
            Collections.sort(layers);
            Coord l = new Coord(0, 0);
            Coord r = new Coord(0, 0);
            long resL = 0, resR = 0;
            for (Integer layer: layers) {
                //out.println("\n" + layer);
                Coord newL = left.get(layer);
                //out.println(newL.x + " " + newL.y);
                Coord newR = right.get(layer);
                //out.println(newR.x + " " + newR.y);
                long leftToRight = Math.abs(newL.x - newR.x) + Math.abs(newL.y - newR.y);

                long a = resL + Math.abs(l.x - newR.x) + Math.abs(l.y - newR.y) + leftToRight;
                long b = resR + Math.abs(r.x - newR.x) + Math.abs(r.y - newR.y) + leftToRight;

                long c = resR + Math.abs(r.x - newL.x) + Math.abs(r.y - newL.y) + leftToRight;
                long d = resL + Math.abs(l.x - newL.x) + Math.abs(l.y - newL.y) + leftToRight;

                resL = Math.min(a, b);
                resR = Math.min(c, d);

                l = left.get(layer);
                r = right.get(layer);
            }
            out.println(Math.min(resL, resR));
        }

        static class Coord {
            long x;
            long y;
            public Coord(int x, int y) {
                this.x = x;
                this.y = y;
            }
        }
    }

    static class InputReader {
        BufferedReader reader;
        StringTokenizer tokenizer;

        InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
    }
}

import java.io.*;
import java.util.*;

public class YetAnother2DWalking {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver solver = new Solver();
        solver.solve(inp, out);
        out.close();
    }

    static class Solver {
        private void solve(InputReader inp, PrintWriter out) {
            int n = inp.nextInt();
            HashMap<Integer, Coord> left = new HashMap<>();
            HashMap<Integer, Coord> right = new HashMap<>();
            Set<Integer> temp = new HashSet<>();
            for (int i = 0; i < n; i++) {
                int x = inp.nextInt();
                int y = inp.nextInt();
                int layer = Math.max(x, y);
                temp.add(layer);
                Coord l = left.getOrDefault(layer, null);
                Coord r = right.getOrDefault(layer, null);
                if (l == null || x < l.x || y > l.y) left.put(layer, new Coord(x, y));
                if (r == null || x > l.x || y < l.y) right.put(layer, new Coord(x, y));
            }
            ArrayList<Integer> layers = new ArrayList<>(temp);
            Collections.sort(layers);
            Coord l = new Coord(0, 0);
            Coord r = new Coord(0, 0);
            long resL = 0, resR = 0;
            for (Integer layer: layers) {
                //out.println("\n" + layer);
                Coord newL = left.get(layer);
                //out.println(newL.x + " " + newL.y);
                Coord newR = right.get(layer);
                //out.println(newR.x + " " + newR.y);
                long leftToRight = Math.abs(newL.x - newR.x) + Math.abs(newL.y - newR.y);

                long a = resL + Math.abs(l.x - newR.x) + Math.abs(l.y - newR.y) + leftToRight;
                long b = resR + Math.abs(r.x - newR.x) + Math.abs(r.y - newR.y) + leftToRight;
                resL = Math.min(a, b);

                a = resR + Math.abs(r.x - newL.x) + Math.abs(r.y - newL.y) + leftToRight;
                b = resL + Math.abs(l.x - newL.x) + Math.abs(l.y - newL.y) + leftToRight;
                resR = Math.min(a, b);

                l = left.get(layer);
                r = right.get(layer);
            }
            out.println(Math.min(resL, resR));
        }

        static class Coord {
            long x;
            long y;
            public Coord(int x, int y) {
                this.x = x;
                this.y = y;
            }
        }
    }

    static class InputReader {
        BufferedReader reader;
        StringTokenizer tokenizer;

        InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
    }
}

import java.io.*;
import java.util.*;
import java.lang.*;
public class F {

    public static void main(String[] args)throws Throwable {

        FastScanner sc = new FastScanner();

        int n = sc.nextInt() + 1;

        Point[] points = new Point[n];

        // add 0,0 point
        points[0] = new Point(0, 0);
        // read given points
        for (int i=1; i<n; i++) {
            points[i] = new Point(sc.nextInt(), sc.nextInt());
        }

        Arrays.sort(points);

        // for (Point p : points) {
        //     System.out.println(p.x + " " + p.y + ", level: " + p.level);
        // }

        Point a = new Point(-1, -1);
        Point b = new Point(-1, -1);
        Point oldA = new Point(-1, -1);
        Point oldB = new Point(-1, -1);

        long distA = 0, distB = 0;
        int tmpDist, tmpA1, tmpA2, tmpB1, tmpB2;

        int i = n-1;
        int cLevel = points[i].level; // current level
        boolean initialLoop = true;

        while (i>-1) {

            oldA = a;
            oldB = b;

            // determine new points
            a = points[i];
            // System.out.println("i " + i);
            while(true) {
                if (i < 1 || points[i-1].level < cLevel) {
                    b = points[i];
                    break;
                }
                i--;
            }
            i--;
            cLevel--;

            // System.out.println("a: " + a.x + " " + a.y);
            // System.out.println("b: " + b.x + " " + b.y);

            tmpDist = a.distTo(b);
            // System.out.println("a-b distance: " + tmpDist);
            distA += tmpDist;
            distB += tmpDist;

            if (initialLoop) {
                initialLoop = false;
                continue;
            }

            tmpA1 = a.distTo(oldA);
            tmpA2 = a.distTo(oldB);

            tmpB1 = b.distTo(oldA);
            tmpB2 = b.distTo(oldB);

            distA += Math.min(tmpA1, tmpA2);
            distB += Math.min(tmpB1, tmpB2);

            if (i < 0) {
                break;
            }
        }

        System.out.println(Math.min(distA, distB));
    }

    static class Point implements Comparable<Point> {

        public int x, y;
        public int level;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
            this.level = x>y ? x : y;
        }

        @Override
        public int compareTo(Point point) {
            if (this.level < point.level) {
                return -1;
            } else if (this.level > point.level) {
                return 1;
            } else {
                if (this.y > point.y) {
                    return -1;
                } else if (this.y < point.y) {
                    return 1;
                } else {
                    if (this.x < point.x) {
                        return -1;
                    } else if (this.x > point.x) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        }

        public int distTo(Point point) {
            return(Math.abs(point.x - this.x) + Math.abs(point.y - this.y));
        }
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                    }
                catch (IOException e) {
                    e.printStackTrace();
                    }
                }
            return st.nextToken();
            }

        int nextInt() {
            return Integer.parseInt(next());
            }

        long nextLong() {
            return Long.parseLong(next());
            }

        double nextDouble() {
            return Double.parseDouble(next());
            }

        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.util.*;
import java.lang.*;
public class F {

    public static void main(String[] args)throws Throwable {

        FastScanner sc = new FastScanner();

        int n = sc.nextInt() + 1;

        Point[] points = new Point[n];

        // add 0,0 point
        points[0] = new Point(0, 0);
        // read given points
        for (int i=1; i<n; i++) {
            points[i] = new Point(sc.nextInt(), sc.nextInt());
        }

        Arrays.sort(points);

        // for (Point p : points) {
        //     System.out.println(p.x + " " + p.y + ", level: " + p.level);
        // }

        Point a = new Point(-1, -1);
        Point b = new Point(-1, -1);
        Point oldA = new Point(-1, -1);
        Point oldB = new Point(-1, -1);

        int distA = 0, distB = 0;
        int tmpDist, tmpA1, tmpA2, tmpB1, tmpB2;

        int i = n-1;
        int cLevel = points[i].level; // current level
        boolean initialLoop = true;

        while (i>-1) {

            oldA = a;
            oldB = b;

            // determine new points
            a = points[i];
            // System.out.println("i " + i);
            while(true) {
                if (i < 1 || points[i-1].level < cLevel) {
                    b = points[i];
                    break;
                }
                i--;
            }
            i--;
            cLevel--;

            // System.out.println("a: " + a.x + " " + a.y);
            // System.out.println("b: " + b.x + " " + b.y);

            tmpDist = a.distTo(b);
            // System.out.println("a-b distance: " + tmpDist);
            distA += tmpDist;
            distB += tmpDist;

            if (initialLoop) {
                initialLoop = false;
                continue;
            }

            tmpA1 = a.distTo(oldA);
            tmpA2 = a.distTo(oldB);

            tmpB1 = b.distTo(oldA);
            tmpB2 = b.distTo(oldB);

            distA += Math.min(tmpA1, tmpA2);
            distB += Math.min(tmpB1, tmpB2);

            if (i < 0) {
                break;
            }
        }

        System.out.println(Math.min(distA, distB));
    }

    static class Point implements Comparable<Point> {

        public int x, y;
        public int level;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
            this.level = x>y ? x : y;
        }

        @Override
        public int compareTo(Point point) {
            if (this.level < point.level) {
                return -1;
            } else if (this.level > point.level) {
                return 1;
            } else {
                if (this.y > point.y) {
                    return -1;
                } else if (this.y < point.y) {
                    return 1;
                } else {
                    if (this.x < point.x) {
                        return -1;
                    } else if (this.x > point.x) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        }

        public int distTo(Point point) {
            return(Math.abs(point.x - this.x) + Math.abs(point.y - this.y));
        }
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                    }
                catch (IOException e) {
                    e.printStackTrace();
                    }
                }
            return st.nextToken();
            }

        int nextInt() {
            return Integer.parseInt(next());
            }

        long nextLong() {
            return Long.parseLong(next());
            }

        double nextDouble() {
            return Double.parseDouble(next());
            }

        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.util.*;
import java.lang.*;
public class F {

    public static void main(String[] args)throws Throwable {

        FastScanner sc = new FastScanner();

        int n = sc.nextInt() + 1;

        Point[] points = new Point[n];

        // add 0,0 point
        points[0] = new Point(0, 0);
        // read given points
        for (int i=1; i<n; i++) {
            points[i] = new Point(sc.nextLong(), sc.nextLong());
        }

        Arrays.sort(points);

        Point a = new Point(-1, -1);
        Point b = new Point(-1, -1);
        Point oldA = new Point(-1, -1);
        Point oldB = new Point(-1, -1);

        long distA = 0, distB = 0;
        long tmpDist, tmpA, tmpB;

        int i = n-1;
        long cLevel = points[i].level; // current level
        boolean initialLoop = true;
        boolean even = true;

        while (i>-1) {

            oldA = a;
            oldB = b;

            // determine new points a, b
            a = points[i];
            while(true) {
                if (i < 1 || points[i-1].level < cLevel) {
                    b = points[i];
                    break;
                }
                i--;
            }
            i--;
            cLevel--;

            tmpDist = a.distTo(b);

            distA += tmpDist;
            distB += tmpDist;

            if (initialLoop) {
                initialLoop = false;
                continue;
            }

            tmpA = a.distTo(oldA);
            tmpB = b.distTo(oldB);

            if(even) {
                distA += tmpA;
                distB += tmpB;
            } else {
                distA += tmpB;
                distB += tmpA;
            }

            even = !even;

            if (i < 0) {
                break;
            }
        }

        System.out.println(Math.min(distA, distB));
    }

    static class Point implements Comparable<Point> {

        public long x, y;
        public long level;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
            this.level = x>y ? x : y;
        }

        @Override
        public int compareTo(Point point) {
            if (this.level < point.level) {
                return -1;
            } else if (this.level > point.level) {
                return 1;
            } else {
                if (this.y > point.y) {
                    return -1;
                } else if (this.y < point.y) {
                    return 1;
                } else {
                    if (this.x < point.x) {
                        return -1;
                    } else if (this.x > point.x) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        }

        public long distTo(Point point) {
            return(Math.abs(point.x - this.x) + Math.abs(point.y - this.y));
        }
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                    }
                catch (IOException e) {
                    e.printStackTrace();
                    }
                }
            return st.nextToken();
            }

        int nextInt() {
            return Integer.parseInt(next());
            }

        long nextLong() {
            return Long.parseLong(next());
            }

        double nextDouble() {
            return Double.parseDouble(next());
            }

        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.util.*;
import java.lang.*;
public class F {

    public static void main(String[] args)throws Throwable {

        FastScanner sc = new FastScanner();

        int n = sc.nextInt() + 1;

        Point[] points = new Point[n];

        // add 0,0 point
        points[0] = new Point(0, 0);
        // read given points
        for (int i=1; i<n; i++) {
            points[i] = new Point(sc.nextLong(), sc.nextLong());
        }

        Arrays.sort(points);

        Point a = new Point(-1, -1);
        Point b = new Point(-1, -1);
        Point oldA = new Point(-1, -1);
        Point oldB = new Point(-1, -1);

        long distA = 0, distB = 0;
        long tmpDist, tmpA1, tmpA2, tmpB1 , tmpB2;

        int i = n-1;

        // current level
        long cLevel = points[i].level;
        boolean initialLoop = true;

        while (i>-1) {

            oldA = a;
            oldB = b;

            // determine new points a, b
            a = points[i];
            while(true) {
                if (i < 1 || points[i-1].level < cLevel) {
                    b = points[i];
                    break;
                }
                i--;
            }
            i--;
            cLevel--;

            // System.out.println("a: " + a.x + " " + a.y);
            // System.out.println("b: " + b.x + " " + b.y);

            tmpDist = a.distTo(b);

            distA += tmpDist;
            distB += tmpDist;

            // A and B must switch each time
            tmpDist = distA;
            distA = distB;
            distB = tmpDist;

            if (initialLoop) {
                initialLoop = false;
                continue;
            }

            tmpA1 = a.distTo(oldA) + distA;
            tmpA2 = a.distTo(oldB) + distB;
            tmpB1 = b.distTo(oldA) + distA;
            tmpB2 = b.distTo(oldB) + distB;

            // System.out.println("---");

            // System.out.println("distA " + distA);
            // System.out.println("distB " + distB);

            // System.out.println("choices for distA " + tmpA1 + " (+"  + a.distTo(oldA) + ") and " + tmpA2 + " (+"  + a.distTo(oldB) + ")");
            // System.out.println("choices for distB " + tmpB1 + " (+"  + b.distTo(oldA) + ") and " + tmpB2 + " (+"  + b.distTo(oldB) + ")");

            distA = Math.min(tmpA1, tmpA2); // take old path A leading to A, or take old path B leading to A
            distB = Math.min(tmpB1, tmpB2);

            // System.out.println("distA " + distA);
            // System.out.println("distB " + distB);

            // System.out.println("---");

            if (i < 0) {
                break;
            }
        }

        System.out.println(Math.min(distA, distB));
    }

    static class Point implements Comparable<Point> {

        public long x, y;
        public long level;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
            this.level = x>y ? x : y;
        }

        @Override
        public int compareTo(Point point) {
            if (this.level < point.level) {
                return -1;
            } else if (this.level > point.level) {
                return 1;
            } else {
                if (this.y > point.y) {
                    return -1;
                } else if (this.y < point.y) {
                    return 1;
                } else {
                    if (this.x < point.x) {
                        return -1;
                    } else if (this.x > point.x) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        }

        public long distTo(Point point) {
            return(Math.abs(point.x - this.x) + Math.abs(point.y - this.y));
        }
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                    }
                catch (IOException e) {
                    e.printStackTrace();
                    }
                }
            return st.nextToken();
            }

        int nextInt() {
            return Integer.parseInt(next());
            }

        long nextLong() {
            return Long.parseLong(next());
            }

        double nextDouble() {
            return Double.parseDouble(next());
            }

        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.util.*;
import java.lang.*;
public class F {

    public static void main(String[] args)throws Throwable {

        FastScanner sc = new FastScanner();

        int n = sc.nextInt() + 1;

        Point[] points = new Point[n];

        // add 0,0 point
        points[0] = new Point(0, 0);
        // read given points
        for (int i=1; i<n; i++) {
            points[i] = new Point(sc.nextInt(), sc.nextInt());
        }

        Arrays.sort(points);

        // for (Point p : points) {
        //     System.out.println(p.x + " " + p.y + ", level: " + p.level);
        // }

        Point a = new Point(-1, -1);
        Point b = new Point(-1, -1);
        Point oldA = new Point(-1, -1);
        Point oldB = new Point(-1, -1);

        long distA = 0, distB = 0;
        long tmpDist, tmpA1, tmpA2, tmpB1, tmpB2;

        int i = n-1;
        long cLevel = points[i].level; // current level
        boolean initialLoop = true;

        while (i>-1) {

            oldA = a;
            oldB = b;

            // determine new points
            a = points[i];
            // System.out.println("i " + i);
            while(true) {
                if (i < 1 || points[i-1].level < cLevel) {
                    b = points[i];
                    break;
                }
                i--;
            }
            i--;
            cLevel--;

            // System.out.println("a: " + a.x + " " + a.y);
            // System.out.println("b: " + b.x + " " + b.y);

            tmpDist = a.distTo(b);
            // System.out.println("a-b distance: " + tmpDist);
            distA += tmpDist;
            distB += tmpDist;

            if (initialLoop) {
                initialLoop = false;
                continue;
            }

            tmpA1 = a.distTo(oldA);
            tmpA2 = a.distTo(oldB);

            tmpB1 = b.distTo(oldA);
            tmpB2 = b.distTo(oldB);

            distA += Math.min(tmpA1, tmpA2);
            distB += Math.min(tmpB1, tmpB2);

            if (i < 0) {
                break;
            }
        }

        System.out.println(Math.min(distA, distB));
    }

    static class Point implements Comparable<Point> {

        public long x, y;
        public long level;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
            this.level = x>y ? x : y;
        }

        @Override
        public int compareTo(Point point) {
            if (this.level < point.level) {
                return -1;
            } else if (this.level > point.level) {
                return 1;
            } else {
                if (this.y > point.y) {
                    return -1;
                } else if (this.y < point.y) {
                    return 1;
                } else {
                    if (this.x < point.x) {
                        return -1;
                    } else if (this.x > point.x) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        }

        public long distTo(Point point) {
            return(Math.abs(point.x - this.x) + Math.abs(point.y - this.y));
        }
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                    }
                catch (IOException e) {
                    e.printStackTrace();
                    }
                }
            return st.nextToken();
            }

        int nextInt() {
            return Integer.parseInt(next());
            }

        long nextLong() {
            return Long.parseLong(next());
            }

        double nextDouble() {
            return Double.parseDouble(next());
            }

        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.util.*;
import java.lang.*;
public class F {

    public static void main(String[] args)throws Throwable {

        FastScanner sc = new FastScanner();

        int n = sc.nextInt() + 1;

        Point[] points = new Point[n];

        // add 0,0 point
        points[0] = new Point(0, 0);
        // read given points
        for (int i=1; i<n; i++) {
            points[i] = new Point(sc.nextLong(), sc.nextLong());
        }

        Arrays.sort(points);

        // for (Point p : points) {
        //     System.out.println(p.x + " " + p.y + ", level: " + p.level);
        // }

        Point a = new Point(-1, -1);
        Point b = new Point(-1, -1);
        Point oldA = new Point(-1, -1);
        Point oldB = new Point(-1, -1);

        long distA = 0, distB = 0;
        long tmpDist, tmpA1, tmpA2, tmpB1, tmpB2;

        int i = n-1;
        long cLevel = points[i].level; // current level
        boolean initialLoop = true;

        while (i>-1) {

            oldA = a;
            oldB = b;

            // determine new points
            a = points[i];
            // System.out.println("i " + i);
            while(true) {
                if (i < 1 || points[i-1].level < cLevel) {
                    b = points[i];
                    break;
                }
                i--;
            }
            i--;
            cLevel--;

            // System.out.println("a: " + a.x + " " + a.y);
            // System.out.println("b: " + b.x + " " + b.y);

            tmpDist = a.distTo(b);
            // System.out.println("a-b distance: " + tmpDist);
            distA += tmpDist;
            distB += tmpDist;

            if (initialLoop) {
                initialLoop = false;
                continue;
            }

            tmpA1 = a.distTo(oldA);
            tmpA2 = a.distTo(oldB);

            tmpB1 = b.distTo(oldA);
            tmpB2 = b.distTo(oldB);

            distA += Math.min(tmpA1, tmpA2);
            distB += Math.min(tmpB1, tmpB2);

            if (i < 0) {
                break;
            }
        }

        System.out.println(Math.min(distA, distB));
    }

    static class Point implements Comparable<Point> {

        public long x, y;
        public long level;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
            this.level = x>y ? x : y;
        }

        @Override
        public int compareTo(Point point) {
            if (this.level < point.level) {
                return -1;
            } else if (this.level > point.level) {
                return 1;
            } else {
                if (this.y > point.y) {
                    return -1;
                } else if (this.y < point.y) {
                    return 1;
                } else {
                    if (this.x < point.x) {
                        return -1;
                    } else if (this.x > point.x) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        }

        public long distTo(Point point) {
            return(Math.abs(point.x - this.x) + Math.abs(point.y - this.y));
        }
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                    }
                catch (IOException e) {
                    e.printStackTrace();
                    }
                }
            return st.nextToken();
            }

        int nextInt() {
            return Integer.parseInt(next());
            }

        long nextLong() {
            return Long.parseLong(next());
            }

        double nextDouble() {
            return Double.parseDouble(next());
            }

        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.util.*;
import java.lang.*;
public class F {

    public static void main(String[] args)throws Throwable {

        FastScanner sc = new FastScanner();

        int n = sc.nextInt() + 1;

        Point[] points = new Point[n];

        // add 0,0 point
        points[0] = new Point(0, 0);
        // read given points
        for (int i=1; i<n; i++) {
            points[i] = new Point(sc.nextLong(), sc.nextLong());
        }

        Arrays.sort(points);

        Point a = new Point(-1, -1);
        Point b = new Point(-1, -1);
        Point oldA = new Point(-1, -1);
        Point oldB = new Point(-1, -1);

        long distA = 0, distB = 0;
        long tmpDist, tmpA, tmpB;

        int i = n-1;

        // current level
        long cLevel = points[i].level;
        boolean initialLoop = true;
        boolean even = true;

        while (i>-1) {

            oldA = a;
            oldB = b;

            // determine new points a, b
            a = points[i];
            while(true) {
                if (i < 1 || points[i-1].level < cLevel) {
                    b = points[i];
                    break;
                }
                i--;
            }
            i--;
            cLevel--;

            tmpDist = a.distTo(b);

            distA += tmpDist;
            distB += tmpDist;

            if (initialLoop) {
                initialLoop = false;
                continue;
            }

            tmpA = a.distTo(oldA);
            tmpB = b.distTo(oldB);

            if(even) {
                distA += tmpA;
                distB += tmpB;
            } else {
                distA += tmpB;
                distB += tmpA;
            }

            even = !even;

            if (i < 0) {
                break;
            }
        }

        System.out.println(Math.min(distA, distB));
    }

    static class Point implements Comparable<Point> {

        public long x, y;
        public long level;

        public Point(long x, long y) {
            this.x = x;
            this.y = y;
            this.level = x>y ? x : y;
        }

        @Override
        public int compareTo(Point point) {
            if (this.level < point.level) {
                return -1;
            } else if (this.level > point.level) {
                return 1;
            } else {
                if (this.y > point.y) {
                    return -1;
                } else if (this.y < point.y) {
                    return 1;
                } else {
                    if (this.x < point.x) {
                        return -1;
                    } else if (this.x > point.x) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            }
        }

        public long distTo(Point point) {
            return(Math.abs(point.x - this.x) + Math.abs(point.y - this.y));
        }
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                    }
                catch (IOException e) {
                    e.printStackTrace();
                    }
                }
            return st.nextToken();
            }

        int nextInt() {
            return Integer.parseInt(next());
            }

        long nextLong() {
            return Long.parseLong(next());
            }

        double nextDouble() {
            return Double.parseDouble(next());
            }

        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;
import java.util.List;

public class Main {

	InputStream is;
	PrintWriter out;
	String INPUT = "";

	private static final long MOD = 998244353L;

	List<Integer> g[];

	void solve() {
		StringBuffer sb = new StringBuffer();
		int N = ni();
		int[][] a = new int[N + 1][2];
		for (int i = 1; i <= N; i++) {
			a[i][0] = ni();
			a[i][1] = ni();
		}

		Arrays.sort(a, new Comparator<int[]>() {
			public int compare(int[] o1, int[] o2) {
				int ret = Math.max(o1[0], o1[1]) - Math.max(o2[0], o2[1]);
				if (ret == 0)
					ret = o1[0] - o2[0];
				if (ret == 0)
					ret = o1[1] - o2[1];
				return ret;
			}
		});
		List<int[]> ends = new ArrayList<int[]>();
		for (int i = 0; i <= N;) {
			int level = Math.max(a[i][0], a[i][1]);
			int j = i + 1;
			for (; j <= N && level == Math.max(a[j][0], a[j][1]); j++)
				;
			ends.add(new int[] { i, j - 1 });
			i = j;
		}

		long dp[] = new long[2];
		for (int i = 1; i < ends.size(); i++) {
			int s0 = ends.get(i - 1)[0];
			int e0 = ends.get(i - 1)[1];
			int s = ends.get(i)[0];
			int e = ends.get(i)[1];
			int curDist = dist(a[s], a[e]); // s->e == e->s
			long cur[] = new long[] {
					// s->e + (1: s0->e0->s, 2: e0->s0->s)
					curDist + Math.min(dp[0] + dist(a[e0], a[s]), dp[1] + dist(a[s0], a[s])),
					// e->s + (1: s0->e0->e, 2: e0->s0->e)
					curDist + Math.min(dp[0] + dist(a[e0], a[e]), dp[1] + dist(a[s0], a[e])) };
			dp = cur;
		}

		out.println(Math.min(dp[0], dp[1]));

	}

	private int dist(int[] p1, int[] p2) {
		return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]);
	}

	private List<Integer>[] getG(int N, int M) {
		List<Integer>[] ret = new List[N];
		for (int i = 0; i < N; i++)
			ret[i] = new ArrayList<Integer>();
		for (int i = 0; i < M; i++) {
			int u = ni() - 1;
			int v = ni() - 1;
			ret[u].add(v);
		}
		return ret;
	}

	private long gcd(long a, long b) {
		while (a != 0) {
			long tmp = b % a;
			b = a;
			a = tmp;
		}
		return b;
	}

	void run() throws Exception {
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		if (!INPUT.isEmpty())
			tr(System.currentTimeMillis() - s + "ms");
	}

	public static void main(String[] args) throws Exception {
		new Main().run();
	}

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;
	private boolean vis[];

	private int readByte() {
		if (lenbuf == -1)
			throw new InputMismatchException();
		if (ptrbuf >= lenbuf) {
			ptrbuf = 0;
			try {
				lenbuf = is.read(inbuf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (lenbuf <= 0)
				return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) {
		return !(c >= 33 && c <= 126);
	}

	private int skip() {
		int b;
		while ((b = readByte()) != -1 && isSpaceChar(b))
			;
		return b;
	}

	private double nd() {
		return Double.parseDouble(ns());
	}

	private char nc() {
		return (char) skip();
	}

	private String ns() {
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != '
									// ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n) {
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while (p < n) {
			if (!(isSpaceChar(b)))
				buf[p++] = (char) b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m) {
		char[][] map = new char[n][];
		for (int i = 0; i < n; i++)
			map[i] = ns(m);
		return map;
	}

	private int[] na(int n) {
		int[] a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = ni();
		return a;
	}

	private Integer[] na2(int n) {
		Integer[] a = new Integer[n];
		for (int i = 0; i < n; i++)
			a[i] = ni();
		return a;
	}

	private int[][] na(int n, int m) {
		int[][] a = new int[n][];
		for (int i = 0; i < n; i++)
			a[i] = na(m);
		return a;
	}

	private Integer[][] na2(int n, int m) {
		Integer[][] a = new Integer[n][];
		for (int i = 0; i < n; i++)
			a[i] = na2(m);
		return a;
	}

	private int ni() {
		int num = 0, b;
		boolean minus = false;
		while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
			;
		if (b == '-') {
			minus = true;
			b = readByte();
		}

		while (true) {
			if (b >= '0' && b <= '9') {
				num = num * 10 + (b - '0');
			} else {
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl() {
		long num = 0;
		int b;
		boolean minus = false;
		while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
			;
		if (b == '-') {
			minus = true;
			b = readByte();
		}

		while (true) {
			if (b >= '0' && b <= '9') {
				num = num * 10 + (b - '0');
			} else {
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private static void tr(Object... o) {
		System.out.println(Arrays.deepToString(o));
	}
}

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;
import java.util.List;

public class Main {

	InputStream is;
	PrintWriter out;
	String INPUT = "";

	private static final long MOD = 998244353L;

	List<Integer> g[];

	void solve() {
		StringBuffer sb = new StringBuffer();
		int N = ni();
		int[][] a = new int[N + 1][2];
		for (int i = 1; i <= N; i++) {
			a[i][0] = ni();
			a[i][1] = ni();
		}

		Arrays.sort(a, new Comparator<int[]>() {
			public int compare(int[] o1, int[] o2) {
				int ret = Math.max(o1[0], o1[1]) - Math.max(o2[0], o2[1]);
				if (ret == 0)
					ret = o1[0] - o2[0];
				if (ret == 0)
					ret = o1[1] - o2[1];
				return ret;
			}
		});
		List<int[]> ends = new ArrayList<int[]>();
		for (int i = 0; i <= N;) {
			int level = Math.max(a[i][0], a[i][1]);
			int j = i + 1;
			for (; j <= N && level == Math.max(a[j][0], a[j][1]); j++)
				;
			ends.add(new int[] { i, j - 1 });
			i = j;
		}

		int dp[] = new int[2];
		for (int i = 1; i < ends.size(); i++) {
			int s0 = ends.get(i - 1)[0];
			int e0 = ends.get(i - 1)[1];
			int s = ends.get(i)[0];
			int e = ends.get(i)[1];
			int curDist = dist(a[s], a[e]); // s->e == e->s
			int cur[] = new int[] {
					// s->e + (1: s0->e0->s, 2: e0->s0->s)
					curDist + Math.min(dp[0] + dist(a[e0], a[s]), dp[1] + dist(a[s0], a[s])),
					// e->s + (1: s0->e0->e, 2: e0->s0->e)
					curDist + Math.min(dp[0] + dist(a[e0], a[e]), dp[1] + dist(a[s0], a[e])) };
			dp = cur;
		}

		out.println(Math.min(dp[0], dp[1]));

	}

	private int dist(int[] p1, int[] p2) {
		return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]);
	}

	private List<Integer>[] getG(int N, int M) {
		List<Integer>[] ret = new List[N];
		for (int i = 0; i < N; i++)
			ret[i] = new ArrayList<Integer>();
		for (int i = 0; i < M; i++) {
			int u = ni() - 1;
			int v = ni() - 1;
			ret[u].add(v);
		}
		return ret;
	}

	private long gcd(long a, long b) {
		while (a != 0) {
			long tmp = b % a;
			b = a;
			a = tmp;
		}
		return b;
	}

	void run() throws Exception {
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		if (!INPUT.isEmpty())
			tr(System.currentTimeMillis() - s + "ms");
	}

	public static void main(String[] args) throws Exception {
		new Main().run();
	}

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;
	private boolean vis[];

	private int readByte() {
		if (lenbuf == -1)
			throw new InputMismatchException();
		if (ptrbuf >= lenbuf) {
			ptrbuf = 0;
			try {
				lenbuf = is.read(inbuf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (lenbuf <= 0)
				return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) {
		return !(c >= 33 && c <= 126);
	}

	private int skip() {
		int b;
		while ((b = readByte()) != -1 && isSpaceChar(b))
			;
		return b;
	}

	private double nd() {
		return Double.parseDouble(ns());
	}

	private char nc() {
		return (char) skip();
	}

	private String ns() {
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != '
									// ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n) {
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while (p < n) {
			if (!(isSpaceChar(b)))
				buf[p++] = (char) b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m) {
		char[][] map = new char[n][];
		for (int i = 0; i < n; i++)
			map[i] = ns(m);
		return map;
	}

	private int[] na(int n) {
		int[] a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = ni();
		return a;
	}

	private Integer[] na2(int n) {
		Integer[] a = new Integer[n];
		for (int i = 0; i < n; i++)
			a[i] = ni();
		return a;
	}

	private int[][] na(int n, int m) {
		int[][] a = new int[n][];
		for (int i = 0; i < n; i++)
			a[i] = na(m);
		return a;
	}

	private Integer[][] na2(int n, int m) {
		Integer[][] a = new Integer[n][];
		for (int i = 0; i < n; i++)
			a[i] = na2(m);
		return a;
	}

	private int ni() {
		int num = 0, b;
		boolean minus = false;
		while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
			;
		if (b == '-') {
			minus = true;
			b = readByte();
		}

		while (true) {
			if (b >= '0' && b <= '9') {
				num = num * 10 + (b - '0');
			} else {
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl() {
		long num = 0;
		int b;
		boolean minus = false;
		while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
			;
		if (b == '-') {
			minus = true;
			b = readByte();
		}

		while (true) {
			if (b >= '0' && b <= '9') {
				num = num * 10 + (b - '0');
			} else {
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private static void tr(Object... o) {
		System.out.println(Arrays.deepToString(o));
	}
}