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);
    }

}

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;
    }
}

//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.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.*;
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.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.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.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.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 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.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));
	}
}