import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
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;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TKSel_E solver = new TKSel_E();
        solver.solve(1, in, out);
        out.close();
    }

    static class TKSel_E {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.ni();
            byte[] a = new byte[n];
            for (int i = 0; i < n; i++) {
                a[i] = (byte) in.ni();
            }

            int max = 100;
            int[] cnt = new int[max + 1];
            for (int i = 0; i < n; i++) {
                cnt[a[i]]++;
            }
            int ncnt = 0;
            for (int i = 1; i <= max; i++) {
                if (cnt[i] > 0)
                    ncnt++;
            }
            if (ncnt <= 2) {
                out.println(n);
                return;
            }
            byte[][][] dp = new byte[max][max + 2][max * max + 3];//dp[i][k][sum]
            dp[0][1][a[0]] = a[0];
            for (int i = 1; i < n; i++) {
                dp[i][1][a[i]] = a[i];
                for (int k = i; k >= 1; k--) {
                    for (int sum = 1; sum <= max * max; sum++) {
                        if (dp[i - 1][k][sum] != 0) {
                            dp[i][k][sum] = dp[i - 1][k][sum];
                            if (dp[i - 1][k][sum] == a[i] && (dp[i][k + 1][sum + a[i]] == 0 || dp[i][k + 1][sum + a[i]] == a[i])) {
                                dp[i][k + 1][sum + a[i]] = a[i];
                            } else {
                                dp[i][k + 1][sum + a[i]] = -1; // different nums
                            }
                        }

                    }

                }
            }

            int ans = 0;
            for (int i = 1; i <= max; i++) {
                if (cnt[i] > 0) {
                    int sum = 0;
                    for (int j = 1; j <= cnt[i]; j++) {
                        sum += i;
                        if (dp[n - 1][j][sum] == i) {
                            ans = Math.max(ans, j);
                        } // else break
                    }
                }
            }
            out.println(ans);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String ns() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    String rl = in.readLine();
                    if (rl == null) {
                        return null;
                    }
                    st = new StringTokenizer(rl);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int ni() {
            return Integer.parseInt(ns());
        }

    }
}


import java.util.*;
import java.io.*;
import java.math.BigInteger;
public class e
{
	public static void main(String[] arg)
	{
		new e();
	}
	long MOD = 1_000_000_007;
	public e()
	{

		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int n = in.nextInt()-1;
		String s1 = in.next();
		String s2 = in.next();
		char[] c = new char['X'];
		c['N'] = 'S';
		c['S'] = 'N';
		c['E'] = 'W';
		c['W'] = 'E';
		StringBuilder sb = new StringBuilder();
		for(int i = n-1; i >= 0; i--)
		{
			sb.append(c[s1.charAt(i)]);
		}
		boolean flag = true;
		long op1 = 0;
		long op2 = 0;
		long pow = 7;
		for(int i = 0; i < n; i++)
		{
			op1 += sb.charAt(i)*pow%MOD;
			pow *= 7;
			op1 %= MOD;
			pow %= MOD;

			op2 += s2.charAt(n-1-i);
			op2 *= 7;
			op2 %= MOD;

			if(op1 == op2) flag = false;
		}
		out.println(flag?"YES":"NO");
		in.close(); out.close();
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created by boris on 26.03.2016.
 */
public class TaskB {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String[] tmp = reader.readLine().split("\\s");

        int pods = Integer.parseInt(tmp[0]);
        int florsc = Integer.parseInt(tmp[1]);
        int doorsc = Integer.parseInt(tmp[2]);

        String[] tmp1 = reader.readLine().split("\\s");

        int fr = Integer.parseInt(tmp1[0]);
        int to = Integer.parseInt(tmp1[1]);

        int frPod = (int) Math.ceil(fr*1.0/doorsc/florsc);
        int frFlor = (int) Math.ceil((fr*1.0-(frPod-1)*(florsc*doorsc))/doorsc);

        int toPod = (int) Math.ceil(to*1.0/doorsc/florsc);
        int toFlor = (int) Math.ceil((to*1.0-(toPod-1)*(florsc*doorsc))/doorsc);

        int time = 0;
        if (frPod == toPod) {
            int florsToGo = Math.abs(toFlor-frFlor);

            if (florsToGo < 3) {
                time += florsToGo*5;
            } else {
                time += 10;
                time += florsToGo;
            }
        } else {
            int florsToGo1 = toFlor-1;
            int florsToGo2 = frFlor-1;

            int podsToGo = Math.min(Math.abs(toPod-frPod), pods-Math.max(toPod, frPod)+Math.min(toPod, frPod));

            if (florsToGo1 < 3) {
                time += florsToGo1*5;
            } else {
                time += 10;
                time += florsToGo1;
            }

            if (florsToGo2 < 3) {
                time += florsToGo2*5;
            } else {
                time += 10;
                time += florsToGo2;
            }

            time += podsToGo*15;
        }

        System.out.println(time);
    }
}


import java.util.*;
import java.io.*;
import static java.lang.Math.*;
import java.math.BigInteger;
public class Main {
    static final long MOD = 998244353, INF = 1_000_000_000_000_000L;
    static final int INf = 1_000_000_000;
    static FastReader reader;
    static PrintWriter writer;
    public static void main(String[] args) {
        Thread t = new Thread(null, new O(), "Integer.MAX_VALUE", 100000000);
        t.start();
    }
    static class O implements Runnable {
        public void run() {
            try {
                magic();
            }
            catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

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

        public FastReader(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[1000000];
            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();
        }
    }
    static int n,m,k[],rem[];
    static Pair offers[];
    static TreeSet<Integer> offers_at[];
    static void magic() throws IOException {
        reader = new FastReader();
        writer = new PrintWriter(System.out, true);
        n = reader.nextInt();
        m = reader.nextInt();
        k = new int[n];
        rem = new int[n];
        for(int i=0;i<n;++i) {
            k[i] = reader.nextInt();
        }
        offers = new Pair[m];
        offers_at = new TreeSet[n];
        for(int i=0;i<n;++i) {
            offers_at[i] = new TreeSet<>();
        }
        for(int i=0;i<m;++i) {
            offers[i] = new Pair(reader.nextInt(), reader.nextInt()-1);
            offers_at[offers[i].y].add(offers[i].x);
        }
        Arrays.sort(offers);
        int low = 1, high = 4000000, mid;
        while(low<high) {
            mid = (low+high)>>1;
            if(check(mid)) {
                if(!check(mid-1)) {
                    low = mid;
                    break;
                }
                else high = --mid;
            }
            else low = ++mid;
        }
        writer.println(low);
    }
    static boolean check(int D) {
        for(int i=0;i<n;++i) {
            rem[i] = k[i];
        }
        int curr = 0, prev = 0;
        for(int i=0;i<m;++i) {
            if(offers[i].x>D) {
                break;
            }
            curr+=(offers[i].x - prev);
            prev = offers[i].x;
            if(offers_at[offers[i].y].lower(D+1)==offers[i].x) {
                int liya = min(curr, rem[offers[i].y]);
                curr-=liya;
                rem[offers[i].y]-=liya;
            }
            else {
                continue;
            }
        }
        curr+=(D-prev);
        int left = 0;
        for(int i=0;i<n;++i) {
            left+=rem[i];
        }
        return curr>=2*left;
    }
    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+")";
        }
    }
}


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

/**
 * 5 5
 * 4 5
 * 1 4 8
 * 4 2 4
 * 4 1 3
 * 3 1 9
 * 4 5 4
 * 2 7
 * 2 7
 * 5 1
 * 6 3
 * 3 2
 *
 * @author pttrung
 */
public class C {

    static boolean[][] pre;

    public static void main(String[] args) {
        Scanner in = new Scanner();
        PrintWriter out = new PrintWriter(System.out);
        int n = in.nextInt();
        pre = new boolean[n][10];
        String[] guess = new String[n];
        int[] b = new int[n];
        int[] c = new int[n];

        for (int i = 0; i < n; i++) {
            guess[i] = in.next();
            process(i, guess[i]);
            b[i] = in.nextInt();
            c[i] = in.nextInt();
        }
        String val = null;
        int count = 0;
        for(int i  = 123; i < 10000; i++){
            String pro;
            if(i < 1000){
                pro = "0" + i;
            }else{
                pro = "" + i;
            }
            if(check(pro, guess, b, c)){
                count++;
                val = pro;
            }
        }
        if(count > 1){
            out.println("Need more data");
        }else if(count == 1){
            out.println(val);
        }else{
            out.println("Incorrect data");
        }

        out.close();
    }

    static void process(int index, String val) {
        for (int i = 0; i < val.length(); i++) {
            int j = val.charAt(i) - '0';
            pre[index][j] = true;
        }
    }

    static boolean check(String val, String[] guess, int[] b, int[] c) {
        boolean[] count = new boolean[10];
        for (int i = 0; i < val.length(); i++) {
            int index = val.charAt(i) - '0';
            if (count[index]) {
                return false;
            }
            count[index] = true;
        }
        for (int i = 0; i < guess.length; i++) {
            int m = 0;
            int n = 0;
            for (int j = 0; j < 4; j++) {
                if (val.charAt(j) == guess[i].charAt(j)) {
                    m++;
                } else if (count[guess[i].charAt(j) - '0']) {
                    n++;
                }
            }
            if (b[i] != m || c[i] != n) {
                return false;
            }
        }
        return true;

    }

    static double distance(Point a, Point b) {
        double total = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
        return Math.sqrt(total);
    }

    static class Point {

        int x, y, z;

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

    static class Scanner {

        BufferedReader br;
        StringTokenizer st;

        public Scanner() {
            // System.setOut(new PrintStream(new BufferedOutputStream(System.out), true));
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public String next() {

            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    throw new RuntimeException();
                }
            }
            return st.nextToken();
        }

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

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

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

        public String nextLine() {
            st = null;
            try {
                return br.readLine();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }

        public boolean endLine() {
            try {
                String next = br.readLine();
                while (next != null && next.trim().isEmpty()) {
                    next = br.readLine();
                }
                if (next == null) {
                    return true;
                }
                st = new StringTokenizer(next);
                return st.hasMoreTokens();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }
    }
}


import java.io.PrintStream;
import java.io.BufferedReader;
import java.util.Comparator;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.math.BigInteger;
import java.util.Collections;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author AlexFetisov
 */
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);
		TaskE_CF_Round solver = new TaskE_CF_Round();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE_CF_Round {
    public static final int MOD = (int)1e9 + 7;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int[] w = Utils.readIntArray(in, 7);
        int[][][] a = new int[7][][];
        for (int i = 1; i <= 7; ++i) {
            a[i-1] = getMatrix(i);
            a[i-1] = MatrixUtils.pow(a[i-1], w[i-1], MOD);
        }
        int[] d = new int[1 << 7];
        int last = -1;
        int[] memo = new int[1 << 7];
        for (int i = 0; i < 7; ++i) {
            for (int j = (1 << (i+1))-1; j >= 0; --j) {
                if (d[j] != 0) {
                    d[j | (1 << i)] = d[j];
                    d[j] = 0;
                }
            }
            if (w[i] != 0) {
                if (last == -1) {
                    d[(1 << (i+1)) - 1] = 1;
                }
                last = i;
                int[] nd = new int[1 << 7];
                for (int j = 0; j < (1 << 7); ++j) {
                    if (d[j] > 0) {
                        for (int k = 0; k < (1 << 7); ++k) {
                            if (a[i].length > j && a[i][j].length > k) {
                                nd[k] += (d[j] * 1L * a[i][j][k]) % MOD;
                                if (nd[k] >= MOD) {
                                    nd[k] -= MOD;
                                }
                            }
                        }
                    }
                }
                int[] temp = d;
                d = nd;
                nd = temp;
                Arrays.fill(nd, 0);
                memo = d.clone();
            }
        }
        out.println(memo[(1 << (last+1)) - 1]);
    }

    private int[][] getMatrix(int w) {
        int[][] a = new int[1 << w][1 << w];
        for (int maskLeft = 0; maskLeft < (1 << w); ++maskLeft) {
            for (int maskRight = 0; maskRight < (1 << w); ++maskRight) {
                for (int mask = 0; mask < (1 << (w-1)); ++mask) {
                    boolean ok = true;
                    for (int bit = 0; bit < w; ++bit) {
                        if (BitUtils.checkBit(maskLeft, bit) && BitUtils.checkBit(maskRight, bit)) {
                            boolean upper = bit == 0 || BitUtils.checkBit(mask, bit-1);
                            boolean lower = bit == w-1 || BitUtils.checkBit(mask, bit);
                            if (upper && lower) {
                                ok = false;
                            }
                        }
                    }
                    if (ok) {
                        ++a[maskLeft][maskRight];
                    }
                }
            }
        }
        return a;
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer stt;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
    }

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

    public String nextString() {
        while (stt == null || !stt.hasMoreTokens()) {
            stt = new StringTokenizer(nextLine());
        }
        return stt.nextToken();
    }

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

}

class Utils {
    public static int[] readIntArray(InputReader in, int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; ++i) {
            a[i] = in.nextInt();
        }
        return a;
    }

}

class MatrixUtils {

    public static int[][] mul(int[][] a, int[][] b, int MOD) {
        int n = a.length;
        int m = a[0].length;
        int k = b[0].length;
        int[][] r = new int[n][k];
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < k; ++j) {
                for (int p = 0; p < m; ++p) {
                    r[i][j] += (a[i][p] * 1L * b[p][j]) % MOD;
                    if (r[i][j] >= MOD) r[i][j] -= MOD;
                }
            }
        }
        return r;
    }

    public static int[][] pow(int[][] aa, long p, int MOD) {
        int[][] a = aa.clone();
        int n = a.length;
        int[][] r = buildOne(n);
        for (long i = p; i > 0; i /= 2) {
            if (i % 2 == 1) r = mul(r, a, MOD);
            a = mul(a, a, MOD);
        }
        return r;
    }

    private static int[][] buildOne(int n) {
        int[][] r = new int[n][n];
        for (int i = 0; i < n; ++i) {
            r[i][i] = 1;
        }
        return r;
    }

}

class BitUtils {
    public static boolean checkBit(int mask, int bit) {
        return (mask & (1 << bit)) > 0;
    }

}


import java.util.Scanner;
import java.lang.Math.*;
public class Main_C {
    static long n;
    private static Scanner enter;

    static long[] a;
    public static void main(String[] args) {
        enter=new Scanner(System.in);
        n=enter.nextLong();
        a=new long[20];
        a[1] = 1;
        for(int i = 2;i <= 16 ;i ++ ) {
            a[i] = a[i-1] *10 + 1;
        }
        System.out.println(sol(n));
    }
    static int sol (long l) {
        int i = 16;
        int r = 0;
        if(l <= 11) {
            return (int) Math.min(l,2+11-l);
        }
        while(a[i-1] > l)i--;
        r = (int) (l/a[i-1]) *(i-1) + sol(l%(a[i-1]));
        if(2*l<a[i])
            return r;
        return Math.min(r, i + sol(a[i] - l));

    }
}


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

public class Main {
  static class Reader {
    static BufferedReader reader;
    static StringTokenizer tokenizer;

    static void init(InputStream input) {
      reader = new BufferedReader(new InputStreamReader(input));
      tokenizer = new StringTokenizer("");
    }

    static String next() throws IOException {
      while (!tokenizer.hasMoreTokens()) {
        tokenizer = new StringTokenizer(reader.readLine());
      }
      return tokenizer.nextToken();
    }

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

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

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

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

  static long[] ones = {0, 1, 11, 111, 1111, 11111, 111111, 1111111, 11111111, 111111111, 1111111111, 11111111111L, 111111111111L, 1111111111111L, 11111111111111L, 111111111111111L, 1111111111111111L};

  public static void main(String[] args) throws Exception {
    Reader.init(System.in);
    long n = Reader.nextLong();
    long res = decompose(n);
    System.out.println(res);
  }

  public static long decompose(long n) {
    if (n <= 6) {
      return n;
    }
    long numOfDigits = getNumOfDigits(n);
    long lower, upper;
    lower = ones[(int) numOfDigits];
    if (n < lower) {
      upper = lower;
      lower = ones[(int) (numOfDigits - 1)];
    } else if (n > lower) {
      upper = ones[(int) (numOfDigits + 1)];
    } else {
      return numOfDigits;
    }
    long resLower = decompose(n % lower) + (n / lower) * getNumOfDigits(lower);
    long resUpper = Long.MAX_VALUE;
    if (upper - n < n) {
      resUpper = decompose(upper - n) + getNumOfDigits(upper);
    }
    return Math.min(resLower, resUpper);
  }

  public static long getNumOfDigits(long n) {
    return (long) Math.floor(Math.log10(n)) + 1;
  }
}


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

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		Task solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}
}

interface Task {
	public void solve(int testNumber, InputReader in, OutputWriter out);
}

class TaskA implements Task {

	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int n=in.readInt(), a=0;
		for (int i=1; i<=n; i++) a^=i;
		for (int i=1; i<n; i++) a^=in.readInt();
		out.printLine(a);
	}

}

class TaskB implements Task {

	int[] arr;
	LinkedList<Pair<Integer, Integer>> mais=new LinkedList<Pair<Integer, Integer>>(), menos=new LinkedList<Pair<Integer, Integer>>();

	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int n=in.readInt();
		long ret=0L, c=0L;
		arr=IOUtils.readIntArray(in, n);
		for (int i=0; i<n; i++) c+=arr[i];
		c/=n;
		for (int i=0; i<n; i++) {
			if (arr[i]<c) menos.addLast(Pair.makePair((int)c-arr[i], i));
			else mais.addLast(Pair.makePair(arr[i]-(int)c, i));
		}
		while (!mais.isEmpty() && !menos.isEmpty()) {
			int x=mais.getFirst().first, y=menos.getFirst().first, d=Math.abs(mais.getFirst().second-menos.getFirst().second);
			ret+=1L*MiscUtils.min(x, y)*d;
			if (x==y) {
				mais.removeFirst();
				menos.removeFirst();
			}
			else if (x<y) {
				mais.removeFirst();
				menos.set(0, Pair.makePair(y-x, menos.getFirst().second));
			}
			else {
				mais.set(0, Pair.makePair(x-y, mais.getFirst().second));
				menos.removeFirst();
			}
		}
		out.printLine(ret);
	}

}

class TaskC implements Task {

	ArrayList<Integer> list=new ArrayList<Integer>();
	long[] pow=new long[16];

	public void solve(int testNumber, InputReader in, OutputWriter out) {
		pow[0]=1L;
		for (int i=1; i<16; i++) pow[i]=10L*pow[i-1]+1L;
		out.printLine(f(in.readLong()));
//		out.printLine(pow);
	}

	int f(long n) {
		if (n<=1L) return (int)n;
		int pos=15, x=0;
		for (; pow[pos]>=n; pos--);
		pos++;
		long m1=0L, m2=pow[pos];
		int x1=0, x2=pos+1;
		while (m1+pow[pos-1]<=n) {
			m1+=pow[pos-1];
			x1+=pos;
		}
		while (m2-pow[pos-1]>=n) {
			m2-=pow[pos-1];
			x2+=pos;
		}
		x1+=f(n-m1);
		x2+=f(m2-n);
		return MiscUtils.min(x1, x2);
	}

}

class TaskD implements Task {

	ArrayList<Pair<Integer, Pair<Integer, Integer>>> edges = new ArrayList<Pair<Integer, Pair<Integer, Integer>>>(),
			used;
	int[] pai, tam;

	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int n = in.readInt(), m = in.readInt();
		int[] a = IOUtils.readIntArray(in, n);
		for (int i = 0; i < m; i++) {
			int x = in.readInt() - 1, y = in.readInt() - 1;
			edges.add(Pair.makePair(MiscUtils.min(a[x], a[y]),
					Pair.makePair(x, y)));
		}
		pai = new int[n];
		tam = new int[n];
		Collections.sort(edges);
		Collections.reverse(edges);
		out.printLine(2.0 * kruskal(n) / n / (n - 1));
	}

	double kruskal(int n) {
		long ret = 0L;
		used = new ArrayList<Pair<Integer, Pair<Integer, Integer>>>();
		for (int i = 0; i < n; i++)
			pai[i] = i;
		Arrays.fill(tam, 1);
		for (Pair<Integer, Pair<Integer, Integer>> par : edges) {
			int w = par.first, x = par.second.first, y = par.second.second;
			if (find(x) != find(y)) {
				ret += 1L * w * tam[find(x)] * tam[find(y)];
				used.add(par);
				if (tam[find(x)] < tam[find(y)]) {
					tam[find(y)] += tam[find(x)];
					pai[find(x)] = find(y);
				} else {
					tam[find(x)] += tam[find(y)];
					pai[find(y)] = find(x);
				}
			}
		}
		return ret;
	}

	int find(int x) {
		if (x == pai[x])
			return x;
		return pai[x] = find(pai[x]);
	}

}

class TaskE implements Task {

	long[] x, y;
	long[][] dp;
	long MOD = 1000000007L;
	Polygon polygon;
	Point[] points;

	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int n = in.readInt();
		x = new long[n];
		y = new long[n];
		IOUtils.readLongArrays(in, x, y);
		points=new Point[n];
		for (int i=0; i<n; i++) points[i]=new Point(x[i], y[i]);
		polygon=new Polygon(points);
		dp = new long[n][n];
		for (int i=0; i<n; i++) Arrays.fill(dp[i], -1L);
		out.printLine(dp(0, n - 1));
//		for (int i=0; i<n; i++) out.printLine(dp[i]);
	}

	long dp(int i, int j) {
		if (dp[i][j]!=-1L) return dp[i][j];
		if (j==i+1) return dp[i][j]=1L;
		dp[i][j]=0L;
		Segment segment=new Segment(points[i], points[j]);
		for (Point point: polygon.vertices) if (segment.contains(point, false)) return dp[i][j];
		for (int k=0; k<i-1; k++) if (segment.intersect(new Segment(points[k], points[k+1]), true)!=null) return dp[i][j];
		for (int k=i+1; k<j-1; k++) if (segment.intersect(new Segment(points[k], points[k+1]), true)!=null) return dp[i][j];
		for (int k=j+1; k<points.length-1; k++) if (segment.intersect(new Segment(points[k], points[k+1]), true)!=null) return dp[i][j];
		if (i!=0 && j!=0 && i!=points.length-1 && j!=points.length-1)
			if (segment.intersect(new Segment(points[0], points[points.length-1]), true)!=null) return dp[i][j];
		Point middle=new Point(0.5*(points[i].x+points[j].x), 0.5*(points[i].y+points[j].y));
		if (!polygon.contains(middle)) return dp[i][j]=0L;
		for (int k=i+1; k<j; k++) dp[i][j]=(dp[i][j]+dp(i, k)*dp(k, j)%MOD)%MOD;
		return dp[i][j];
	}

	class Polygon {
		public final Point[] vertices;
		private Segment[] sides;

		public Polygon(Point... vertices) {
			this.vertices = vertices.clone();
		}

		public double square() {
			double sum = 0;
			for (int i = 1; i < vertices.length; i++)
				sum += (vertices[i].x - vertices[i - 1].x)
						* (vertices[i].y + vertices[i - 1].y);
			sum += (vertices[0].x - vertices[vertices.length - 1].x)
					* (vertices[0].y + vertices[vertices.length - 1].y);
			return Math.abs(sum) / 2;
		}

		public Point center() {
			double sx = 0;
			double sy = 0;
			for (Point point : vertices) {
				sx += point.x;
				sy += point.y;
			}
			return new Point(sx / vertices.length, sy / vertices.length);
		}

		public boolean contains(Point point) {
			return contains(point, false);
		}

		public boolean contains(Point point, boolean strict) {
			for (Segment segment : sides()) {
				if (segment.contains(point, true))
					return !strict;
			}
			double totalAngle = GeometryUtils.canonicalAngle(Math.atan2(
					vertices[0].y - point.y, vertices[0].x - point.x)
					- Math.atan2(vertices[vertices.length - 1].y - point.y,
							vertices[vertices.length - 1].x - point.x));
			for (int i = 1; i < vertices.length; i++) {
				totalAngle += GeometryUtils.canonicalAngle(Math.atan2(
						vertices[i].y - point.y, vertices[i].x - point.x)
						- Math.atan2(vertices[i - 1].y - point.y,
								vertices[i - 1].x - point.x));
			}
			return Math.abs(totalAngle) > Math.PI;
		}

		public Segment[] sides() {
			if (sides == null) {
				sides = new Segment[vertices.length];
				for (int i = 0; i < vertices.length - 1; i++)
					sides[i] = new Segment(vertices[i], vertices[i + 1]);
				sides[sides.length - 1] = new Segment(
						vertices[vertices.length - 1], vertices[0]);
			}
			return sides;
		}

		public double perimeter() {
			double result = vertices[0].distance(vertices[vertices.length - 1]);
			for (int i = 1; i < vertices.length; i++)
				result += vertices[i].distance(vertices[i - 1]);
			return result;
		}
	}

	class Segment {
		public final Point a;
		public final Point b;
		private double distance = Double.NaN;
		private Line line = null;

		public Segment(Point a, Point b) {
			this.a = a;
			this.b = b;
		}

		public double length() {
			if (Double.isNaN(distance))
				distance = a.distance(b);
			return distance;
		}

		public double distance(Point point) {
			double length = length();
			double left = point.distance(a);
			if (length < GeometryUtils.epsilon)
				return left;
			double right = point.distance(b);
			if (left * left > right * right + length * length)
				return right;
			if (right * right > left * left + length * length)
				return left;
			return point.distance(line());
		}

		public Point intersect(Segment other, boolean includeEnds) {
			Line line = line();
			Line otherLine = other.a.line(other.b);
			if (line.parallel(otherLine))
				return null;
			Point intersection = line.intersect(otherLine);
			if (contains(intersection, includeEnds)
					&& other.contains(intersection, includeEnds))
				return intersection;
			else
				return null;
		}

		public boolean contains(Point point, boolean includeEnds) {
			if (a.equals(point) || b.equals(point))
				return includeEnds;
			if (a.equals(b))
				return false;
			Line line = line();
			if (!line.contains(point))
				return false;
			Line perpendicular = line.perpendicular(a);
			double aValue = perpendicular.value(a);
			double bValue = perpendicular.value(b);
			double pointValue = perpendicular.value(point);
			return aValue < pointValue && pointValue < bValue
					|| bValue < pointValue && pointValue < aValue;
		}

		public Line line() {
			if (line == null)
				line = a.line(b);
			return line;
		}

		public Point middle() {
			return new Point((a.x + b.x) / 2, (a.y + b.y) / 2);
		}

		public Point intersect(Line line) {
			Line selfLine = line();
			Point intersect = selfLine.intersect(line);
			if (intersect == null)
				return null;
			if (contains(intersect, true))
				return intersect;
			return null;
		}

		public double distance(Segment other) {
			Line line = line();
			Line otherLine = other.line();
			Point p = line == null || otherLine == null ? null : line
					.intersect(otherLine);
			if (p != null && contains(p, true) && other.contains(p, true))
				return 0;
			return Math.min(Math.min(other.distance(a), other.distance(b)),
					Math.min(distance(other.a), distance(other.b)));
		}
	}

	class Point {
		public final double x;
		public final double y;

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

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

		public Line line(Point other) {
			if (equals(other))
				return null;
			double a = other.y - y;
			double b = x - other.x;
			double c = -a * x - b * y;
			return new Line(a, b, c);
		}

		@Override
		public boolean equals(Object o) {
			if (this == o)
				return true;
			if (o == null || getClass() != o.getClass())
				return false;

			Point point = (Point) o;

			return Math.abs(x - point.x) <= GeometryUtils.epsilon
					&& Math.abs(y - point.y) <= GeometryUtils.epsilon;
		}

		@Override
		public int hashCode() {
			int result;
			long temp;
			temp = x != +0.0d ? Double.doubleToLongBits(x) : 0L;
			result = (int) (temp ^ (temp >>> 32));
			temp = y != +0.0d ? Double.doubleToLongBits(y) : 0L;
			result = 31 * result + (int) (temp ^ (temp >>> 32));
			return result;
		}

		public double distance(Point other) {
			return GeometryUtils.fastHypot(x - other.x, y - other.y);
		}

		public double distance(Line line) {
			return Math.abs(line.a * x + line.b * y + line.c);
		}

		public double value() {
			return GeometryUtils.fastHypot(x, y);
		}

		public double angle() {
			return Math.atan2(y, x);
		}

		public Point rotate(double angle) {
			double nx = x * Math.cos(angle) - y * Math.sin(angle);
			double ny = y * Math.cos(angle) + x * Math.sin(angle);
			return new Point(nx, ny);
		}
	}

	class Line {
		public final double a;
		public final double b;
		public final double c;

		public Line(Point p, double angle) {
			a = Math.sin(angle);
			b = -Math.cos(angle);
			c = -p.x * a - p.y * b;
		}

		public Line(double a, double b, double c) {
			double h = GeometryUtils.fastHypot(a, b);
			this.a = a / h;
			this.b = b / h;
			this.c = c / h;
		}

		public Point intersect(Line other) {
			if (parallel(other))
				return null;
			double determinant = b * other.a - a * other.b;
			double x = (c * other.b - b * other.c) / determinant;
			double y = (a * other.c - c * other.a) / determinant;
			return new Point(x, y);
		}

		public boolean parallel(Line other) {
			return Math.abs(a * other.b - b * other.a) < GeometryUtils.epsilon;
		}

		public boolean contains(Point point) {
			return Math.abs(value(point)) < GeometryUtils.epsilon;
		}

		public Line perpendicular(Point point) {
			return new Line(-b, a, b * point.x - a * point.y);
		}

		public double value(Point point) {
			return a * point.x + b * point.y + c;
		}

		public double distance(Point center) {
			return Math.abs(value(center));
		}

		@Override
		public boolean equals(Object o) {
			if (this == o)
				return true;
			if (o == null || getClass() != o.getClass())
				return false;

			Line line = (Line) o;

			if (!parallel(line))
				return false;
			if (Math.abs(a * line.c - c * line.a) > GeometryUtils.epsilon
					|| Math.abs(b * line.c - c * line.b) > GeometryUtils.epsilon)
				return false;

			return true;
		}
	}

}

class GeometryUtils {
	public static double epsilon = 1e-5;

	public static double fastHypot(double... x) {
		if (x.length == 0)
			return 0;
		else if (x.length == 1)
			return Math.abs(x[0]);
		else {
			double sumSquares = 0;
			for (double value : x)
				sumSquares += value * value;
			return Math.sqrt(sumSquares);
		}
	}

	public static double fastHypot(double x, double y) {
		return Math.sqrt(x * x + y * y);
	}

	public static double fastHypot(double[] x, double[] y) {
		if (x.length == 0)
			return 0;
		else if (x.length == 1)
			return Math.abs(x[0] - y[0]);
		else {
			double sumSquares = 0;
			for (int i = 0; i < x.length; i++) {
				double diff = x[i] - y[i];
				sumSquares += diff * diff;
			}
			return Math.sqrt(sumSquares);
		}
	}

	public static double fastHypot(int[] x, int[] y) {
		if (x.length == 0)
			return 0;
		else if (x.length == 1)
			return Math.abs(x[0] - y[0]);
		else {
			double sumSquares = 0;
			for (int i = 0; i < x.length; i++) {
				double diff = x[i] - y[i];
				sumSquares += diff * diff;
			}
			return Math.sqrt(sumSquares);
		}
	}

	public static double missileTrajectoryLength(double v, double angle,
			double g) {
		return (v * v * Math.sin(2 * angle)) / g;
	}

	public static double sphereVolume(double radius) {
		return 4 * Math.PI * radius * radius * radius / 3;
	}

	public static double triangleSquare(double first, double second,
			double third) {
		double p = (first + second + third) / 2;
		return Math.sqrt(p * (p - first) * (p - second) * (p - third));
	}

	public static double canonicalAngle(double angle) {
		while (angle > Math.PI)
			angle -= 2 * Math.PI;
		while (angle < -Math.PI)
			angle += 2 * Math.PI;
		return angle;
	}

	public static double positiveAngle(double angle) {
		while (angle > 2 * Math.PI - GeometryUtils.epsilon)
			angle -= 2 * Math.PI;
		while (angle < -GeometryUtils.epsilon)
			angle += 2 * Math.PI;
		return angle;
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
				outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void print(char[] array) {
		writer.print(array);
	}

	public void print(Object... objects) {
		for (int i = 0; i < objects.length; i++) {
			if (i != 0)
				writer.print(' ');
			writer.print(objects[i]);
		}
	}

	public void print(int[] array) {
		for (int i = 0; i < array.length; i++) {
			if (i != 0)
				writer.print(' ');
			writer.print(array[i]);
		}
	}

	public void print(long[] array) {
		for (int i = 0; i < array.length; i++) {
			if (i != 0)
				writer.print(' ');
			writer.print(array[i]);
		}
	}

	public void print(Collection<Integer> collection) {
		boolean first = true;
		for (Integer iterator : collection) {
			if (first)
				first = false;
			else
				writer.print(' ');
			writer.print(iterator);
		}
	}

	public void printLine(int[] array) {
		print(array);
		writer.println();
	}

	public void printLine(long[] array) {
		print(array);
		writer.println();
	}

	public void printLine(Collection<Integer> collection) {
		print(collection);
		writer.println();
	}

	public void printLine() {
		writer.println();
	}

	public void printLine(Object... objects) {
		print(objects);
		writer.println();
	}

	public void print(char i) {
		writer.print(i);
	}

	public void printLine(char i) {
		writer.println(i);
	}

	public void printLine(char[] array) {
		writer.println(array);
	}

	public void printFormat(String format, Object... objects) {
		writer.printf(format, objects);
	}

	public void close() {
		writer.close();
	}

	public void flush() {
		writer.flush();
	}

	public void print(long i) {
		writer.print(i);
	}

	public void printLine(long i) {
		writer.println(i);
	}

	public void print(int i) {
		writer.print(i);
	}

	public void printLine(int i) {
		writer.println(i);
	}
}

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 int peek() {
		if (numChars == -1)
			return -1;
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				return -1;
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar];
	}

	public int readInt() {
		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 readLong() {
		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 String readString() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			if (Character.isValidCodePoint(c))
				res.appendCodePoint(c);
			c = read();
		} while (!isSpaceChar(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private String readLine0() {
		StringBuilder buf = new StringBuilder();
		int c = read();
		while (c != '\n' && c != -1) {
			if (c != '\r')
				buf.appendCodePoint(c);
			c = read();
		}
		return buf.toString();
	}

	public String readLine() {
		String s = readLine0();
		while (s.trim().length() == 0)
			s = readLine0();
		return s;
	}

	public String readLine(boolean ignoreEmptyLines) {
		if (ignoreEmptyLines)
			return readLine();
		else
			return readLine0();
	}

	public BigInteger readBigInteger() {
		try {
			return new BigInteger(readString());
		} catch (NumberFormatException e) {
			throw new InputMismatchException();
		}
	}

	public char readCharacter() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		return (char) c;
	}

	public double readDouble() {
		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, readInt());
			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, readInt());
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				m /= 10;
				res += (c - '0') * m;
				c = read();
			}
		}
		return res * sgn;
	}

	public boolean isExhausted() {
		int value;
		while (isSpaceChar(value = peek()) && value != -1)
			read();
		return value == -1;
	}

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

	public SpaceCharFilter getFilter() {
		return filter;
	}

	public void setFilter(SpaceCharFilter filter) {
		this.filter = filter;
	}

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

class IOUtils {
	public static Pair<Integer, Integer> readIntPair(InputReader in) {
		int first = in.readInt();
		int second = in.readInt();
		return Pair.makePair(first, second);
	}

	public static Pair<Long, Long> readLongPair(InputReader in) {
		long first = in.readLong();
		long second = in.readLong();
		return Pair.makePair(first, second);
	}

	public static int[] readIntArray(InputReader in, int size) {
		int[] array = new int[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readInt();
		return array;
	}

	public static long[] readLongArray(InputReader in, int size) {
		long[] array = new long[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readLong();
		return array;
	}

	public static double[] readDoubleArray(InputReader in, int size) {
		double[] array = new double[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readDouble();
		return array;
	}

	public static String[] readStringArray(InputReader in, int size) {
		String[] array = new String[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readString();
		return array;
	}

	public static char[] readCharArray(InputReader in, int size) {
		char[] array = new char[size];
		for (int i = 0; i < size; i++)
			array[i] = in.readCharacter();
		return array;
	}

	public static Pair<Integer, Integer>[] readIntPairArray(InputReader in,
			int size) {
		@SuppressWarnings({ "unchecked" })
		Pair<Integer, Integer>[] result = new Pair[size];
		for (int i = 0; i < size; i++)
			result[i] = readIntPair(in);
		return result;
	}

	public static Pair<Long, Long>[] readLongPairArray(InputReader in, int size) {
		@SuppressWarnings({ "unchecked" })
		Pair<Long, Long>[] result = new Pair[size];
		for (int i = 0; i < size; i++)
			result[i] = readLongPair(in);
		return result;
	}

	public static void readIntArrays(InputReader in, int[]... arrays) {
		for (int i = 0; i < arrays[0].length; i++) {
			for (int j = 0; j < arrays.length; j++)
				arrays[j][i] = in.readInt();
		}
	}

	public static void readLongArrays(InputReader in, long[]... arrays) {
		for (int i = 0; i < arrays[0].length; i++) {
			for (int j = 0; j < arrays.length; j++)
				arrays[j][i] = in.readLong();
		}
	}

	public static void readDoubleArrays(InputReader in, double[]... arrays) {
		for (int i = 0; i < arrays[0].length; i++) {
			for (int j = 0; j < arrays.length; j++)
				arrays[j][i] = in.readDouble();
		}
	}

	public static char[][] readTable(InputReader in, int rowCount,
			int columnCount) {
		char[][] table = new char[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readCharArray(in, columnCount);
		return table;
	}

	public static int[][] readIntTable(InputReader in, int rowCount,
			int columnCount) {
		int[][] table = new int[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readIntArray(in, columnCount);
		return table;
	}

	public static double[][] readDoubleTable(InputReader in, int rowCount,
			int columnCount) {
		double[][] table = new double[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readDoubleArray(in, columnCount);
		return table;
	}

	public static long[][] readLongTable(InputReader in, int rowCount,
			int columnCount) {
		long[][] table = new long[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readLongArray(in, columnCount);
		return table;
	}

	public static String[][] readStringTable(InputReader in, int rowCount,
			int columnCount) {
		String[][] table = new String[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readStringArray(in, columnCount);
		return table;
	}

	public static String readText(InputReader in) {
		StringBuilder result = new StringBuilder();
		while (true) {
			int character = in.read();
			if (character == '\r')
				continue;
			if (character == -1)
				break;
			result.append((char) character);
		}
		return result.toString();
	}

	public static void readStringArrays(InputReader in, String[]... arrays) {
		for (int i = 0; i < arrays[0].length; i++) {
			for (int j = 0; j < arrays.length; j++)
				arrays[j][i] = in.readString();
		}
	}

	public static void printTable(OutputWriter out, char[][] table) {
		for (char[] row : table)
			out.printLine(new String(row));
	}
}

class Pair<U, V> implements Comparable<Pair<U, V>> {
	public final U first;
	public final V second;

	public static <U, V> Pair<U, V> makePair(U first, V second) {
		return new Pair<U, V>(first, second);
	}

	private Pair(U first, V second) {
		this.first = first;
		this.second = second;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;

		Pair<?, ?> pair = (Pair<?, ?>) o;

		return !(first != null ? !first.equals(pair.first) : pair.first != null)
				&& !(second != null ? !second.equals(pair.second)
						: pair.second != null);

	}

	@Override
	public int hashCode() {
		int result = first != null ? first.hashCode() : 0;
		result = 31 * result + (second != null ? second.hashCode() : 0);
		return result;
	}

	public Pair<V, U> swap() {
		return makePair(second, first);
	}

	@Override
	public String toString() {
		return "(" + first + "," + second + ")";
	}

	@SuppressWarnings({ "unchecked" })
	public int compareTo(Pair<U, V> o) {
		int value = ((Comparable<U>) first).compareTo(o.first);
		if (value != 0)
			return value;
		return ((Comparable<V>) second).compareTo(o.second);
	}
}

class BidirectionalGraph extends Graph {
	public int[] transposedEdge;

	public BidirectionalGraph(int vertexCount) {
		this(vertexCount, vertexCount);
	}

	public BidirectionalGraph(int vertexCount, int edgeCapacity) {
		super(vertexCount, 2 * edgeCapacity);
		transposedEdge = new int[2 * edgeCapacity];
	}

	public static BidirectionalGraph createGraph(int vertexCount, int[] from,
			int[] to) {
		BidirectionalGraph graph = new BidirectionalGraph(vertexCount,
				from.length);
		for (int i = 0; i < from.length; i++)
			graph.addSimpleEdge(from[i], to[i]);
		return graph;
	}

	public static BidirectionalGraph createWeightedGraph(int vertexCount,
			int[] from, int[] to, long[] weight) {
		BidirectionalGraph graph = new BidirectionalGraph(vertexCount,
				from.length);
		for (int i = 0; i < from.length; i++)
			graph.addWeightedEdge(from[i], to[i], weight[i]);
		return graph;
	}

	public static BidirectionalGraph createFlowGraph(int vertexCount,
			int[] from, int[] to, long[] capacity) {
		BidirectionalGraph graph = new BidirectionalGraph(vertexCount,
				from.length * 2);
		for (int i = 0; i < from.length; i++)
			graph.addFlowEdge(from[i], to[i], capacity[i]);
		return graph;
	}

	public static BidirectionalGraph createFlowWeightedGraph(int vertexCount,
			int[] from, int[] to, long[] weight, long[] capacity) {
		BidirectionalGraph graph = new BidirectionalGraph(vertexCount,
				from.length * 2);
		for (int i = 0; i < from.length; i++)
			graph.addFlowWeightedEdge(from[i], to[i], weight[i], capacity[i]);
		return graph;
	}

	@Override
	public int addEdge(int fromID, int toID, long weight, long capacity,
			int reverseEdge) {
		int lastEdgeCount = edgeCount;
		super.addEdge(fromID, toID, weight, capacity, reverseEdge);
		super.addEdge(toID, fromID, weight, capacity, reverseEdge == -1 ? -1
				: reverseEdge + 1);
		this.transposedEdge[lastEdgeCount] = lastEdgeCount + 1;
		this.transposedEdge[lastEdgeCount + 1] = lastEdgeCount;
		return lastEdgeCount;
	}

	@Override
	protected int entriesPerEdge() {
		return 2;
	}

	@Override
	public final int transposed(int id) {
		return transposedEdge[id];
	}

	@Override
	protected void ensureEdgeCapacity(int size) {
		if (size > edgeCapacity()) {
			super.ensureEdgeCapacity(size);
			transposedEdge = resize(transposedEdge, edgeCapacity());
		}
	}
}

class Graph {
	public static final int REMOVED_BIT = 0;

	protected int vertexCount;
	protected int edgeCount;

	private int[] firstOutbound;
	private int[] firstInbound;

	private Edge[] edges;
	private int[] nextInbound;
	private int[] nextOutbound;
	private int[] from;
	private int[] to;
	private long[] weight;
	private long[] capacity;
	private int[] reverseEdge;
	private int[] flags;

	public Graph(int vertexCount) {
		this(vertexCount, vertexCount);
	}

	public Graph(int vertexCount, int edgeCapacity) {
		this.vertexCount = vertexCount;
		firstOutbound = new int[vertexCount];
		Arrays.fill(firstOutbound, -1);

		from = new int[edgeCapacity];
		to = new int[edgeCapacity];
		nextOutbound = new int[edgeCapacity];
		flags = new int[edgeCapacity];
	}

	public static Graph createGraph(int vertexCount, int[] from, int[] to) {
		Graph graph = new Graph(vertexCount, from.length);
		for (int i = 0; i < from.length; i++)
			graph.addSimpleEdge(from[i], to[i]);
		return graph;
	}

	public static Graph createWeightedGraph(int vertexCount, int[] from,
			int[] to, long[] weight) {
		Graph graph = new Graph(vertexCount, from.length);
		for (int i = 0; i < from.length; i++)
			graph.addWeightedEdge(from[i], to[i], weight[i]);
		return graph;
	}

	public static Graph createFlowGraph(int vertexCount, int[] from, int[] to,
			long[] capacity) {
		Graph graph = new Graph(vertexCount, from.length * 2);
		for (int i = 0; i < from.length; i++)
			graph.addFlowEdge(from[i], to[i], capacity[i]);
		return graph;
	}

	public static Graph createFlowWeightedGraph(int vertexCount, int[] from,
			int[] to, long[] weight, long[] capacity) {
		Graph graph = new Graph(vertexCount, from.length * 2);
		for (int i = 0; i < from.length; i++)
			graph.addFlowWeightedEdge(from[i], to[i], weight[i], capacity[i]);
		return graph;
	}

	public static Graph createTree(int[] parent) {
		Graph graph = new Graph(parent.length + 1, parent.length);
		for (int i = 0; i < parent.length; i++)
			graph.addSimpleEdge(parent[i], i + 1);
		return graph;
	}

	public int addEdge(int fromID, int toID, long weight, long capacity,
			int reverseEdge) {
		ensureEdgeCapacity(edgeCount + 1);
		if (firstOutbound[fromID] != -1)
			nextOutbound[edgeCount] = firstOutbound[fromID];
		else
			nextOutbound[edgeCount] = -1;
		firstOutbound[fromID] = edgeCount;
		if (firstInbound != null) {
			if (firstInbound[toID] != -1)
				nextInbound[edgeCount] = firstInbound[toID];
			else
				nextInbound[edgeCount] = -1;
			firstInbound[toID] = edgeCount;
		}
		this.from[edgeCount] = fromID;
		this.to[edgeCount] = toID;
		if (capacity != 0) {
			if (this.capacity == null)
				this.capacity = new long[from.length];
			this.capacity[edgeCount] = capacity;
		}
		if (weight != 0) {
			if (this.weight == null)
				this.weight = new long[from.length];
			this.weight[edgeCount] = weight;
		}
		if (reverseEdge != -1) {
			if (this.reverseEdge == null) {
				this.reverseEdge = new int[from.length];
				Arrays.fill(this.reverseEdge, 0, edgeCount, -1);
			}
			this.reverseEdge[edgeCount] = reverseEdge;
		}
		if (edges != null)
			edges[edgeCount] = createEdge(edgeCount);
		return edgeCount++;
	}

	protected final GraphEdge createEdge(int id) {
		return new GraphEdge(id);
	}

	public final int addFlowWeightedEdge(int from, int to, long weight,
			long capacity) {
		if (capacity == 0) {
			return addEdge(from, to, weight, 0, -1);
		} else {
			int lastEdgeCount = edgeCount;
			addEdge(to, from, -weight, 0, lastEdgeCount + entriesPerEdge());
			return addEdge(from, to, weight, capacity, lastEdgeCount);
		}
	}

	protected int entriesPerEdge() {
		return 1;
	}

	public final int addFlowEdge(int from, int to, long capacity) {
		return addFlowWeightedEdge(from, to, 0, capacity);
	}

	public final int addWeightedEdge(int from, int to, long weight) {
		return addFlowWeightedEdge(from, to, weight, 0);
	}

	public final int addSimpleEdge(int from, int to) {
		return addWeightedEdge(from, to, 0);
	}

	public final int vertexCount() {
		return vertexCount;
	}

	public final int edgeCount() {
		return edgeCount;
	}

	protected final int edgeCapacity() {
		return from.length;
	}

	public final Edge edge(int id) {
		initEdges();
		return edges[id];
	}

	public final int firstOutbound(int vertex) {
		int id = firstOutbound[vertex];
		while (id != -1 && isRemoved(id))
			id = nextOutbound[id];
		return id;
	}

	public final int nextOutbound(int id) {
		id = nextOutbound[id];
		while (id != -1 && isRemoved(id))
			id = nextOutbound[id];
		return id;
	}

	public final int firstInbound(int vertex) {
		initInbound();
		int id = firstInbound[vertex];
		while (id != -1 && isRemoved(id))
			id = nextInbound[id];
		return id;
	}

	public final int nextInbound(int id) {
		initInbound();
		id = nextInbound[id];
		while (id != -1 && isRemoved(id))
			id = nextInbound[id];
		return id;
	}

	public final int source(int id) {
		return from[id];
	}

	public final int destination(int id) {
		return to[id];
	}

	public final long weight(int id) {
		if (weight == null)
			return 0;
		return weight[id];
	}

	public final long capacity(int id) {
		if (capacity == null)
			return 0;
		return capacity[id];
	}

	public final long flow(int id) {
		if (reverseEdge == null)
			return 0;
		return capacity[reverseEdge[id]];
	}

	public final void pushFlow(int id, long flow) {
		if (flow == 0)
			return;
		if (flow > 0) {
			if (capacity(id) < flow)
				throw new IllegalArgumentException("Not enough capacity");
		} else {
			if (flow(id) < -flow)
				throw new IllegalArgumentException("Not enough capacity");
		}
		capacity[id] -= flow;
		capacity[reverseEdge[id]] += flow;
	}

	public int transposed(int id) {
		return -1;
	}

	public final int reverse(int id) {
		if (reverseEdge == null)
			return -1;
		return reverseEdge[id];
	}

	public final void addVertices(int count) {
		ensureVertexCapacity(vertexCount + count);
		Arrays.fill(firstOutbound, vertexCount, vertexCount + count, -1);
		if (firstInbound != null)
			Arrays.fill(firstInbound, vertexCount, vertexCount + count, -1);
		vertexCount += count;
	}

	protected final void initEdges() {
		if (edges == null) {
			edges = new Edge[from.length];
			for (int i = 0; i < edgeCount; i++)
				edges[i] = createEdge(i);
		}
	}

	public final void removeVertex(int vertex) {
		int id = firstOutbound[vertex];
		while (id != -1) {
			removeEdge(id);
			id = nextOutbound[id];
		}
		initInbound();
		id = firstInbound[vertex];
		while (id != -1) {
			removeEdge(id);
			id = nextInbound[id];
		}
	}

	private void initInbound() {
		if (firstInbound == null) {
			firstInbound = new int[firstOutbound.length];
			Arrays.fill(firstInbound, 0, vertexCount, -1);
			nextInbound = new int[from.length];
			for (int i = 0; i < edgeCount; i++) {
				nextInbound[i] = firstInbound[to[i]];
				firstInbound[to[i]] = i;
			}
		}
	}

	public final boolean flag(int id, int bit) {
		return (flags[id] >> bit & 1) != 0;
	}

	public final void setFlag(int id, int bit) {
		flags[id] |= 1 << bit;
	}

	public final void removeFlag(int id, int bit) {
		flags[id] &= -1 - (1 << bit);
	}

	public final void removeEdge(int id) {
		setFlag(id, REMOVED_BIT);
	}

	public final void restoreEdge(int id) {
		removeFlag(id, REMOVED_BIT);
	}

	public final boolean isRemoved(int id) {
		return flag(id, REMOVED_BIT);
	}

	public final Iterable<Edge> outbound(final int id) {
		initEdges();
		return new Iterable<Edge>() {
			public Iterator<Edge> iterator() {
				return new EdgeIterator(id, firstOutbound, nextOutbound);
			}
		};
	}

	public final Iterable<Edge> inbound(final int id) {
		initEdges();
		initInbound();
		return new Iterable<Edge>() {
			public Iterator<Edge> iterator() {
				return new EdgeIterator(id, firstInbound, nextInbound);
			}
		};
	}

	protected void ensureEdgeCapacity(int size) {
		if (from.length < size) {
			int newSize = Math.max(size, 2 * from.length);
			if (edges != null)
				edges = resize(edges, newSize);
			from = resize(from, newSize);
			to = resize(to, newSize);
			nextOutbound = resize(nextOutbound, newSize);
			if (nextInbound != null)
				nextInbound = resize(nextInbound, newSize);
			if (weight != null)
				weight = resize(weight, newSize);
			if (capacity != null)
				capacity = resize(capacity, newSize);
			if (reverseEdge != null)
				reverseEdge = resize(reverseEdge, newSize);
			flags = resize(flags, newSize);
		}
	}

	private void ensureVertexCapacity(int size) {
		if (firstOutbound.length < size) {
			int newSize = Math.max(size, 2 * from.length);
			firstOutbound = resize(firstOutbound, newSize);
			if (firstInbound != null)
				firstInbound = resize(firstInbound, newSize);
		}
	}

	protected final int[] resize(int[] array, int size) {
		int[] newArray = new int[size];
		System.arraycopy(array, 0, newArray, 0, array.length);
		return newArray;
	}

	private long[] resize(long[] array, int size) {
		long[] newArray = new long[size];
		System.arraycopy(array, 0, newArray, 0, array.length);
		return newArray;
	}

	private Edge[] resize(Edge[] array, int size) {
		Edge[] newArray = new Edge[size];
		System.arraycopy(array, 0, newArray, 0, array.length);
		return newArray;
	}

	public final boolean isSparse() {
		return vertexCount == 0 || edgeCount * 20 / vertexCount <= vertexCount;
	}

	protected class GraphEdge implements Edge {
		protected int id;

		protected GraphEdge(int id) {
			this.id = id;
		}

		public int getSource() {
			return source(id);
		}

		public int getDestination() {
			return destination(id);
		}

		public long getWeight() {
			return weight(id);
		}

		public long getCapacity() {
			return capacity(id);
		}

		public long getFlow() {
			return flow(id);
		}

		public void pushFlow(long flow) {
			Graph.this.pushFlow(id, flow);
		}

		public boolean getFlag(int bit) {
			return flag(id, bit);
		}

		public void setFlag(int bit) {
			Graph.this.setFlag(id, bit);
		}

		public void removeFlag(int bit) {
			Graph.this.removeFlag(id, bit);
		}

		public int getTransposedID() {
			return transposed(id);
		}

		public Edge getTransposedEdge() {
			int reverseID = getTransposedID();
			if (reverseID == -1)
				return null;
			initEdges();
			return edge(reverseID);
		}

		public int getReverseID() {
			return reverse(id);
		}

		public Edge getReverseEdge() {
			int reverseID = getReverseID();
			if (reverseID == -1)
				return null;
			initEdges();
			return edge(reverseID);
		}

		public int getID() {
			return id;
		}

		public void remove() {
			removeEdge(id);
		}

		public void restore() {
			restoreEdge(id);
		}
	}

	public class EdgeIterator implements Iterator<Edge> {
		private int edgeID;
		private final int[] next;
		private int lastID = -1;

		public EdgeIterator(int id, int[] first, int[] next) {
			this.next = next;
			edgeID = nextEdge(first[id]);
		}

		private int nextEdge(int id) {
			while (id != -1 && isRemoved(id))
				id = next[id];
			return id;
		}

		public boolean hasNext() {
			return edgeID != -1;
		}

		public Edge next() {
			if (edgeID == -1)
				throw new NoSuchElementException();
			lastID = edgeID;
			edgeID = nextEdge(next[lastID]);
			return edges[lastID];
		}

		public void remove() {
			if (lastID == -1)
				throw new IllegalStateException();
			removeEdge(lastID);
			lastID = -1;
		}
	}

}

interface Edge {
	public int getSource();

	public int getDestination();

	public long getWeight();

	public long getCapacity();

	public long getFlow();

	public void pushFlow(long flow);

	public boolean getFlag(int bit);

	public void setFlag(int bit);

	public void removeFlag(int bit);

	public int getTransposedID();

	public Edge getTransposedEdge();

	public int getReverseID();

	public Edge getReverseEdge();

	public int getID();

	public void remove();

	public void restore();
}

class MiscUtils {
	public static final int[] DX4 = { 1, 0, -1, 0 };
	public static final int[] DY4 = { 0, -1, 0, 1 };
	public static final int[] DX8 = { 1, 1, 1, 0, -1, -1, -1, 0 };
	public static final int[] DY8 = { -1, 0, 1, 1, 1, 0, -1, -1 };
	public static final int[] DX_KNIGHT = { 2, 1, -1, -2, -2, -1, 1, 2 };
	public static final int[] DY_KNIGHT = { 1, 2, 2, 1, -1, -2, -2, -1 };

	private static final String[] ROMAN_TOKENS = { "M", "CM", "D", "CD", "C",
			"XC", "L", "XL", "X", "IX", "V", "IV", "I" };
	private static final int[] ROMAN_VALUES = { 1000, 900, 500, 400, 100, 90,
			50, 40, 10, 9, 5, 4, 1 };

	public static long josephProblem(long n, int k) {
		if (n == 1)
			return 0;
		if (k == 1)
			return n - 1;
		if (k > n)
			return (josephProblem(n - 1, k) + k) % n;
		long count = n / k;
		long result = josephProblem(n - count, k);
		result -= n % k;
		if (result < 0)
			result += n;
		else
			result += result / (k - 1);
		return result;
	}

	public static boolean isValidCell(int row, int column, int rowCount,
			int columnCount) {
		return row >= 0 && row < rowCount && column >= 0
				&& column < columnCount;
	}

	public static List<Integer> getPath(int[] last, int destination) {
		List<Integer> path = new ArrayList<Integer>();
		while (destination != -1) {
			path.add(destination);
			destination = last[destination];
		}
		Collections.reverse(path);
		return path;
	}

	public static List<Integer> getPath(int[][] lastIndex,
			int[][] lastPathNumber, int destination, int pathNumber) {
		List<Integer> path = new ArrayList<Integer>();
		while (destination != -1 || pathNumber != 0) {
			path.add(destination);
			int nextDestination = lastIndex[destination][pathNumber];
			pathNumber = lastPathNumber[destination][pathNumber];
			destination = nextDestination;
		}
		Collections.reverse(path);
		return path;
	}

	public static long maximalRectangleSum(long[][] array) {
		int n = array.length;
		int m = array[0].length;
		long[][] partialSums = new long[n + 1][m + 1];
		for (int i = 0; i < n; i++) {
			long rowSum = 0;
			for (int j = 0; j < m; j++) {
				rowSum += array[i][j];
				partialSums[i + 1][j + 1] = partialSums[i][j + 1] + rowSum;
			}
		}
		long result = Long.MIN_VALUE;
		for (int i = 0; i < m; i++) {
			for (int j = i; j < m; j++) {
				long minPartialSum = 0;
				for (int k = 1; k <= n; k++) {
					long current = partialSums[k][j + 1] - partialSums[k][i];
					result = Math.max(result, current - minPartialSum);
					minPartialSum = Math.min(minPartialSum, current);
				}
			}
		}
		return result;
	}

	public static int parseIP(String ip) {
		String[] components = ip.split("[.]");
		int result = 0;
		for (int i = 0; i < 4; i++)
			result += (1 << (24 - 8 * i)) * Integer.parseInt(components[i]);
		return result;
	}

	public static String buildIP(int mask) {
		StringBuilder result = new StringBuilder();
		for (int i = 0; i < 4; i++) {
			if (i != 0)
				result.append('.');
			result.append(mask >> (24 - 8 * i) & 255);
		}
		return result.toString();
	}

	public static long binarySearch(long from, long to,
			Function<Long, Boolean> function) {
		while (from < to) {
			long argument = from + (to - from) / 2;
			if (function.value(argument))
				to = argument;
			else
				from = argument + 1;
		}
		return from;
	}

	public static <T> boolean equals(T first, T second) {
		return first == null && second == null || first != null
				&& first.equals(second);
	}

	public static boolean isVowel(char ch) {
		ch = Character.toUpperCase(ch);
		return ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U'
				|| ch == 'Y';
	}

	public static boolean isStrictVowel(char ch) {
		ch = Character.toUpperCase(ch);
		return ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U';
	}

	public static String convertToRoman(int number) {
		StringBuilder result = new StringBuilder();
		for (int i = 0; i < ROMAN_TOKENS.length; i++) {
			while (number >= ROMAN_VALUES[i]) {
				number -= ROMAN_VALUES[i];
				result.append(ROMAN_TOKENS[i]);
			}
		}
		return result.toString();
	}

	public static int convertFromRoman(String number) {
		int result = 0;
		for (int i = 0; i < ROMAN_TOKENS.length; i++) {
			while (number.startsWith(ROMAN_TOKENS[i])) {
				number = number.substring(ROMAN_TOKENS[i].length());
				result += ROMAN_VALUES[i];
			}
		}
		return result;
	}

	public static int distance(int x1, int y1, int x2, int y2) {
		int dx = x1 - x2;
		int dy = y1 - y2;
		return dx * dx + dy * dy;
	}

	public static <T extends Comparable<T>> T min(T first, T second) {
		if (first.compareTo(second) <= 0)
			return first;
		return second;
	}

	public static <T extends Comparable<T>> T max(T first, T second) {
		if (first.compareTo(second) <= 0)
			return second;
		return first;
	}

	public static void decreaseByOne(int[]... arrays) {
		for (int[] array : arrays) {
			for (int i = 0; i < array.length; i++)
				array[i]--;
		}
	}

	public static int[] getIntArray(String s) {
		String[] tokens = s.split(" ");
		int[] result = new int[tokens.length];
		for (int i = 0; i < result.length; i++)
			result[i] = Integer.parseInt(tokens[i]);
		return result;
	}
}

interface Function<A, V> {
	public abstract V value(A argument);
}

interface IntComparator {
	public static final IntComparator DEFAULT = new IntComparator() {
		public int compare(int first, int second) {
			if (first < second)
				return -1;
			if (first > second)
				return 1;
			return 0;
		}
	};

	public static final IntComparator REVERSE = new IntComparator() {
		public int compare(int first, int second) {
			if (first < second)
				return 1;
			if (first > second)
				return -1;
			return 0;
		}
	};

	public int compare(int first, int second);
}

class DFSOrder {
	public final int[] position;
	public final int[] end;

	public DFSOrder(Graph graph) {
		this(graph, 0);
	}

	public DFSOrder(Graph graph, int root) {
		int count = graph.vertexCount();
		position = new int[count];
		end = new int[count];
		int[] edge = new int[count];
		int[] stack = new int[count];
		for (int i = 0; i < count; i++)
			edge[i] = graph.firstOutbound(i);
		stack[0] = root;
		int size = 1;
		position[root] = 0;
		int index = 0;
		while (size > 0) {
			int current = stack[size - 1];
			if (edge[current] == -1) {
				end[current] = index;
				size--;
			} else {
				int next = graph.destination(edge[current]);
				edge[current] = graph.nextOutbound(edge[current]);
				position[next] = ++index;
				stack[size++] = next;
			}
		}
	}

	public DFSOrder(BidirectionalGraph graph) {
		this(graph, 0);
	}

	public DFSOrder(BidirectionalGraph graph, int root) {
		int count = graph.vertexCount();
		position = new int[count];
		end = new int[count];
		int[] edge = new int[count];
		int[] stack = new int[count];
		int[] last = new int[count];
		for (int i = 0; i < count; i++)
			edge[i] = graph.firstOutbound(i);
		stack[0] = root;
		last[root] = -1;
		int size = 1;
		position[root] = 0;
		int index = 0;
		while (size > 0) {
			int current = stack[size - 1];
			if (edge[current] == -1) {
				end[current] = index;
				size--;
			} else {
				int next = graph.destination(edge[current]);
				if (next == last[current]) {
					edge[current] = graph.nextOutbound(edge[current]);
					continue;
				}
				edge[current] = graph.nextOutbound(edge[current]);
				position[next] = ++index;
				last[next] = current;
				stack[size++] = next;
			}
		}
	}
}

abstract class IntervalTree {
	protected int size;

	protected IntervalTree(int size) {
		this(size, true);
	}

	public IntervalTree(int size, boolean shouldInit) {
		this.size = size;
		int nodeCount = Math.max(1, Integer.highestOneBit(size) << 2);
		initData(size, nodeCount);
		if (shouldInit)
			init();
	}

	protected abstract void initData(int size, int nodeCount);

	protected abstract void initAfter(int root, int left, int right, int middle);

	protected abstract void initBefore(int root, int left, int right, int middle);

	protected abstract void initLeaf(int root, int index);

	protected abstract void updatePostProcess(int root, int left, int right,
			int from, int to, long delta, int middle);

	protected abstract void updatePreProcess(int root, int left, int right,
			int from, int to, long delta, int middle);

	protected abstract void updateFull(int root, int left, int right, int from,
			int to, long delta);

	protected abstract long queryPostProcess(int root, int left, int right,
			int from, int to, int middle, long leftResult, long rightResult);

	protected abstract void queryPreProcess(int root, int left, int right,
			int from, int to, int middle);

	protected abstract long queryFull(int root, int left, int right, int from,
			int to);

	protected abstract long emptySegmentResult();

	public void init() {
		if (size == 0)
			return;
		init(0, 0, size - 1);
	}

	private void init(int root, int left, int right) {
		if (left == right) {
			initLeaf(root, left);
		} else {
			int middle = (left + right) >> 1;
			initBefore(root, left, right, middle);
			init(2 * root + 1, left, middle);
			init(2 * root + 2, middle + 1, right);
			initAfter(root, left, right, middle);
		}
	}

	public void update(int from, int to, long delta) {
		update(0, 0, size - 1, from, to, delta);
	}

	protected void update(int root, int left, int right, int from, int to,
			long delta) {
		if (left > to || right < from)
			return;
		if (left >= from && right <= to) {
			updateFull(root, left, right, from, to, delta);
			return;
		}
		int middle = (left + right) >> 1;
		updatePreProcess(root, left, right, from, to, delta, middle);
		update(2 * root + 1, left, middle, from, to, delta);
		update(2 * root + 2, middle + 1, right, from, to, delta);
		updatePostProcess(root, left, right, from, to, delta, middle);
	}

	public long query(int from, int to) {
		return query(0, 0, size - 1, from, to);
	}

	protected long query(int root, int left, int right, int from, int to) {
		if (left > to || right < from)
			return emptySegmentResult();
		if (left >= from && right <= to)
			return queryFull(root, left, right, from, to);
		int middle = (left + right) >> 1;
		queryPreProcess(root, left, right, from, to, middle);
		long leftResult = query(2 * root + 1, left, middle, from, to);
		long rightResult = query(2 * root + 2, middle + 1, right, from, to);
		return queryPostProcess(root, left, right, from, to, middle,
				leftResult, rightResult);
	}
}

class LCA {
	private final long[] order;
	private final int[] position;
	private final IntervalTree lcaTree;
	private final int[] level;

	public LCA(Graph graph) {
		this(graph, 0);
	}

	public LCA(Graph graph, int root) {
		order = new long[2 * graph.vertexCount() - 1];
		position = new int[graph.vertexCount()];
		level = new int[graph.vertexCount()];
		int[] index = new int[graph.vertexCount()];
		for (int i = 0; i < index.length; i++)
			index[i] = graph.firstOutbound(i);
		int[] last = new int[graph.vertexCount()];
		int[] stack = new int[graph.vertexCount()];
		stack[0] = root;
		int size = 1;
		int j = 0;
		last[root] = -1;
		Arrays.fill(position, -1);
		while (size > 0) {
			int vertex = stack[--size];
			if (position[vertex] == -1)
				position[vertex] = j;
			order[j++] = vertex;
			if (last[vertex] != -1)
				level[vertex] = level[last[vertex]] + 1;
			while (index[vertex] != -1
					&& last[vertex] == graph.destination(index[vertex]))
				index[vertex] = graph.nextOutbound(index[vertex]);
			if (index[vertex] != -1) {
				stack[size++] = vertex;
				stack[size++] = graph.destination(index[vertex]);
				last[graph.destination(index[vertex])] = vertex;
				index[vertex] = graph.nextOutbound(index[vertex]);
			}
		}
		lcaTree = new ReadOnlyIntervalTree(order) {
			@Override
			protected long joinValue(long left, long right) {
				if (left == -1)
					return right;
				if (right == -1)
					return left;
				if (level[((int) left)] < level[((int) right)])
					return left;
				return right;
			}

			@Override
			protected long neutralValue() {
				return -1;
			}
		};
		lcaTree.init();
	}

	public int getPosition(int vertex) {
		return position[vertex];
	}

	public int getLCA(int first, int second) {
		return (int) lcaTree.query(Math.min(position[first], position[second]),
				Math.max(position[first], position[second]));
	}

	public int getLevel(int vertex) {
		return level[vertex];
	}

	public int getPathLength(int first, int second) {
		return level[first] + level[second] - 2 * level[getLCA(first, second)];
	}
}

abstract class LongIntervalTree extends IntervalTree {
	protected long[] value;
	protected long[] delta;

	protected LongIntervalTree(int size) {
		this(size, true);
	}

	public LongIntervalTree(int size, boolean shouldInit) {
		super(size, shouldInit);
	}

	@Override
	protected void initData(int size, int nodeCount) {
		value = new long[nodeCount];
		delta = new long[nodeCount];
	}

	protected abstract long joinValue(long left, long right);

	protected abstract long joinDelta(long was, long delta);

	protected abstract long accumulate(long value, long delta, int length);

	protected abstract long neutralValue();

	protected abstract long neutralDelta();

	protected long initValue(int index) {
		return neutralValue();
	}

	@Override
	protected void initAfter(int root, int left, int right, int middle) {
		value[root] = joinValue(value[2 * root + 1], value[2 * root + 2]);
		delta[root] = neutralDelta();
	}

	@Override
	protected void initBefore(int root, int left, int right, int middle) {
	}

	@Override
	protected void initLeaf(int root, int index) {
		value[root] = initValue(index);
		delta[root] = neutralDelta();
	}

	@Override
	protected void updatePostProcess(int root, int left, int right, int from,
			int to, long delta, int middle) {
		value[root] = joinValue(value[2 * root + 1], value[2 * root + 2]);
	}

	@Override
	protected void updatePreProcess(int root, int left, int right, int from,
			int to, long delta, int middle) {
		pushDown(root, left, middle, right);
	}

	protected void pushDown(int root, int left, int middle, int right) {
		value[2 * root + 1] = accumulate(value[2 * root + 1], delta[root],
				middle - left + 1);
		value[2 * root + 2] = accumulate(value[2 * root + 2], delta[root],
				right - middle);
		delta[2 * root + 1] = joinDelta(delta[2 * root + 1], delta[root]);
		delta[2 * root + 2] = joinDelta(delta[2 * root + 2], delta[root]);
		delta[root] = neutralDelta();
	}

	@Override
	protected void updateFull(int root, int left, int right, int from, int to,
			long delta) {
		value[root] = accumulate(value[root], delta, right - left + 1);
		this.delta[root] = joinDelta(this.delta[root], delta);
	}

	@Override
	protected long queryPostProcess(int root, int left, int right, int from,
			int to, int middle, long leftResult, long rightResult) {
		return joinValue(leftResult, rightResult);
	}

	@Override
	protected void queryPreProcess(int root, int left, int right, int from,
			int to, int middle) {
		pushDown(root, left, middle, right);
	}

	@Override
	protected long queryFull(int root, int left, int right, int from, int to) {
		return value[root];
	}

	@Override
	protected long emptySegmentResult() {
		return neutralValue();
	}
}

class SumIntervalTree extends LongIntervalTree {
	public SumIntervalTree(int size) {
		super(size);
	}

	@Override
	protected long joinValue(long left, long right) {
		return left + right;
	}

	@Override
	protected long joinDelta(long was, long delta) {
		return was + delta;
	}

	@Override
	protected long accumulate(long value, long delta, int length) {
		return value + delta * length;
	}

	@Override
	protected long neutralValue() {
		return 0;
	}

	@Override
	protected long neutralDelta() {
		return 0;
	}
}

abstract class ReadOnlyIntervalTree extends IntervalTree {
	protected long[] value;
	protected long[] array;

	protected ReadOnlyIntervalTree(long[] array) {
		super(array.length, false);
		this.array = array;
		init();
	}

	@Override
	protected void initData(int size, int nodeCount) {
		value = new long[nodeCount];
	}

	@Override
	protected void initAfter(int root, int left, int right, int middle) {
		value[root] = joinValue(value[2 * root + 1], value[2 * root + 2]);
	}

	@Override
	protected void initBefore(int root, int left, int right, int middle) {
	}

	@Override
	protected void initLeaf(int root, int index) {
		value[root] = array[index];
	}

	@Override
	protected void updatePostProcess(int root, int left, int right, int from,
			int to, long delta, int middle) {
		throw new UnsupportedOperationException();
	}

	@Override
	protected void updatePreProcess(int root, int left, int right, int from,
			int to, long delta, int middle) {
		throw new UnsupportedOperationException();
	}

	@Override
	protected void updateFull(int root, int left, int right, int from, int to,
			long delta) {
		throw new UnsupportedOperationException();
	}

	@Override
	protected long queryPostProcess(int root, int left, int right, int from,
			int to, int middle, long leftResult, long rightResult) {
		return joinValue(leftResult, rightResult);
	}

	@Override
	protected void queryPreProcess(int root, int left, int right, int from,
			int to, int middle) {
	}

	@Override
	protected long queryFull(int root, int left, int right, int from, int to) {
		return value[root];
	}

	@Override
	protected long emptySegmentResult() {
		return neutralValue();
	}

	@Override
	public void update(int from, int to, long delta) {
		throw new UnsupportedOperationException();
	}

	@Override
	protected void update(int root, int left, int right, int from, int to,
			long delta) {
		throw new UnsupportedOperationException();
	}

	protected abstract long neutralValue();

	protected abstract long joinValue(long left, long right);
}


/*
If you want to aim high, aim high
Don't let that studying and grades consume you
Just live life young
******************************
If I'm the sun, you're the moon
Because when I go up, you go down
*******************************
I'm working for the day I will surpass you
https://www.a2oj.com/Ladder16.html
*/
import java.util.*;
import java.io.*;
import java.math.*;

   public class x440C
   {
      static long[] pow;
      public static void main(String omkar[]) throws Exception
      {
         BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));
         StringTokenizer st = new StringTokenizer(infile.readLine());
         String input = st.nextToken();
         int N = input.length();
         int[] arr = new int[N];
         for(int i=0; i < N; i++)
            arr[i] = Integer.parseInt(input.charAt(i)+"");
         //brute force
         pow = new long[16];
         pow[0] = 1L;
         for(int i=1; i <= 15; i++)
            pow[i] = pow[i-1]*10;
         long start = Long.parseLong(input);
         System.out.println(solve(start));
      }
      public static int solve(long x)
      {
         if(x <= 11)
         {
            if(x == 11)
               return 2;
            else if(x == 10)
               return 3;
            else if(x == 9)
               return 4;
            else if(x == 8)
               return 5;
            else if(x == 7)
               return 6;
            else
               return (int)x;
         }
         int len = (x+"").length();
         long boof = 0L;
         for(int i=0; i <= len; i++)
            boof += pow[i];
         int res = Integer.MAX_VALUE;
         if(x > boof-x)
            res = Math.min(res, len+1+solve(boof-x));
         boof -= pow[len];
         for(int d=1; d <= 9; d++)
         {
            boof *= d;
            if(d == x/pow[len-1] || d+1 == x/pow[len-1])//(x > boof-x)
               res = Math.min(res, len*d+solve(Math.abs(boof-x)));
            boof /= d;
         }
         return res;
      }
   }


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

public class C {

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;
	boolean eof;

	static long[] ONES = new long[17];
	static {
		ONES[1] = 1;
		for (int i = 2; i < 17; i++) {
			ONES[i] = 10 * ONES[i - 1] + 1;
		}
	}

	long go(long x, int len) {
		x = Math.abs(x);
//		System.err.println(x + " " + len);
		if (x % ONES[len] == 0) {
			return x / ONES[len] * len;
		}
		long low = x / ONES[len];
		long high = low + 1;

		long ret1 = low * len + go(x - low * ONES[len], len - 1);
		long ret2 = high * len + go(high * ONES[len] - x, len - 1);
		return Math.min(ret1, ret2);
	}

	long solve(long x) {
		return go(x, 16);
	}

	C() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		out.println(solve(nextLong()));
		out.close();
	}

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

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return null;
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			eof = true;
			return null;
		}
	}

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

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

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


import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
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);
		TaskC solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskC {
    long a[] = new long[17];
    HashMap<Long, Long> cache = new HashMap<Long, Long>();

    private long calc(long n) {
        if(n==0) {
            return 0;
        }
        if(cache.containsKey(n)){
            return cache.get(n);
        }
        for (int i = 0; i < 17; i++) {
            if(a[i] >= n) {
                if(a[i] == n) {
                    cache.put(n, (long)i+1);
                    return i+1;
                }

                long k = n/a[i-1];
                long c1 = i*k + calc(n-a[i - 1]*k);

                k = (a[i]-n)/a[i-1];
                long c2 = i + 1 + i*k+ calc(a[i]-a[i-1]*k-n);

                long min = Math.min(c1, c2);
                cache.put(n, min);
                return min;
            }
        }
        throw new RuntimeException();
    }

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        long n = in.nextLong();

        a[0] = 1;
        for (int i = 1; i < 17; i++) {
            a[i] = a[i-1]*10 + 1;
        }

        out.println(calc(n));

    }
}

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

    public long nextLong() {
        try {
            int c = read();

            while (isWhiteSpace(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long ret = 0;
            while (c >= 0 && !isWhiteSpace(c)) {
                if (c < '0' || c > '9') {
                    throw new RuntimeException();
                }
                ret = ret * 10 + c - '0';
                c = read();
            }
            return ret * sgn;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

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

    static boolean isWhiteSpace(int c) {
        return c >= 0 && c <= 32;
    }

}


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

public class c12 {

    public static void main(String[] args)throws Exception {
        long n=ll();
        System.out.println(solve(n));
    }

    private static long solve(long n) {
        if (n<=10){
            return Math.min(n,2+(11-n));
        }
        long h=geth(n);
        long l=getl(n);
        long c1=((h+"").length())+Math.abs(((h-n)/l)*(l+"").length())+solve(Math.abs((h-n))%l);
        long c2=Math.abs(((n)/l)*(l+"").length())+solve(Math.abs((n))%l);
        return Math.min(c1,c2);
    }

    private static long geth(long n) {
        String s=n+"";
        long t1=get(s.length());
        if (t1>=n)return t1;
        else return get(s.length()+1);
    }

    private static long getl(long n) {
        String s=n+"";
        long t1=get(s.length());
        if (t1<n)return t1;
        return get(s.length()-1);
    }
    static long get(int l){
        switch (l){
        case 1:return 1;case 4:return 1111;
        case 2:return 11;case 5:return 11111;
        case 3:return 111;case 6:return 111111;
        case 7:return 1111111;case 10:return 1111111111;
        case 8:return 11111111;case 11:return 11111111111l;
        case 9:return 111111111;case 12:return 111111111111l;
        case 13:return 1111111111111l;
        case 14:return 11111111111111l;
        case 15:return 111111111111111l;
        case 16:return 1111111111111111l;
        default :return 11111111111111111l;

        }
    }

    static BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int in() throws IOException{
        if (st==null || !st.hasMoreTokens()){
            st=new StringTokenizer(buf.readLine());
        }
        return Integer.parseInt(st.nextToken());
    }
    static long ll() throws IOException{
        if (st==null || !st.hasMoreTokens()){
            st=new StringTokenizer(buf.readLine());
        }
        return Long.parseLong(st.nextToken());
    }
    static String str() throws IOException{
        if (st==null || !st.hasMoreTokens()){
            st=new StringTokenizer(buf.readLine());
        }
        return (st.nextToken());
    }
        static double dub() throws IOException{
            if (st==null || !st.hasMoreTokens()){
                st=new StringTokenizer(buf.readLine());
            }
            return Double.parseDouble(st.nextToken());
    }
}


import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.io.InputStream;

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

class TaskC {
    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int shift = 15;
        int maxn = 60;

        int[][][] dp = new int[maxn + 1][maxn + 1][shift * 2 + 1];
        for (int[][] e1 : dp) {
            for (int[] e2 : e1) Arrays.fill(e2, Integer.MAX_VALUE);
        }
        dp[maxn][maxn][shift] = 0;
        char[] d = ("000" + in.next()).toCharArray();
        for (int i = d.length - 1; i >= 0; i--) {
            int digit = d[i] - '0';
            for (int plus = maxn; plus >= 0; plus--) {
                for (int minus = maxn; minus >= 0; minus--) {
                    for (int carry = 0; carry <= 2 * shift; carry++) {
                        if (plus + 1 <= maxn)
                            dp[plus][minus][carry] = Math.min(dp[plus][minus][carry], dp[plus + 1][minus][carry]);
                        if (minus + 1 <= maxn)
                            dp[plus][minus][carry] = Math.min(dp[plus][minus][carry], dp[plus][minus + 1][carry]);
                    }
                }
            }
            int[][][] next = new int[maxn + 1][maxn + 1][shift * 2 + 1];
            for (int[][] e1 : next) {
                for (int[] e2 : e1) Arrays.fill(e2, Integer.MAX_VALUE);
            }
            for (int plus = maxn; plus >= 0; plus--) {
                for (int minus = maxn; minus >= 0; minus--) {
                    for (int carry = 0; carry <= 2 * shift; carry++) {
                        int val = dp[plus][minus][carry];
                        if (val == Integer.MAX_VALUE) continue;
                        int realCarry = carry - shift;
                        int curN = plus - minus + realCarry;
                        int curD = curN % 10;
                        if (curD < 0) curD += 10;
                        int newCarry = (curN - curD) / 10;
                        if (curD != digit) continue;
                        next[plus][minus][newCarry + shift] = Math.min(next[plus][minus][newCarry + shift], plus + minus + val);
                    }
                }
            }
            dp = next;
        }
        int ans = Integer.MAX_VALUE;
        for (int i = 0; i <= maxn; i++) {
            for (int j = 0; j <= maxn; j++) ans = Math.min(ans, dp[i][j][shift]);
        }
        out.println(ans);
    }
}

class FastScanner extends BufferedReader {

    public FastScanner(InputStream is) {
        super(new InputStreamReader(is));
    }

    public int read() {
        try {
            int ret = super.read();
//            if (isEOF && ret < 0) {
//                throw new InputMismatchException();
//            }
//            isEOF = ret == -1;
            return ret;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

    public String next() {
        StringBuilder sb = new StringBuilder();
        int c = read();
        while (isWhiteSpace(c)) {
            c = read();
        }
        if (c < 0) {
            return null;
        }
        while (c >= 0 && !isWhiteSpace(c)) {
            sb.appendCodePoint(c);
            c = read();
        }
        return sb.toString();
    }

    static boolean isWhiteSpace(int c) {
        return c >= 0 && c <= 32;
    }

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

}

class FastPrinter extends PrintWriter {

    public FastPrinter(OutputStream out) {
        super(out);
    }

    public FastPrinter(Writer out) {
        super(out);
    }

}


import java.io.BufferedReader;
    import java.io.*;
    import java.util.StringTokenizer;

    /**
     * Author: Luis Manuel Díaz Barón
     * Problem:
     * Online Judge:
     * Idea:
     * Fecha: 20/02/2013
     */

    public class Main {

        static MyScanner sc;
        static MyWriter pw;
        static String filePathWin="d:\\lmo.in";
        static String filePathLinux="/media/luismo/Trabajo/lmo.in";
        public static void main(String[] args) throws IOException {
            sc = new MyScanner(System.in);

    //        sc = new MyScanner(new FileReader(filePathWin));
            // sc = new MyScanner(new FileReader(filePathLinux));

            pw = new MyWriter(System.out);

            while(sc.canRead())
                SolveSingleProblem();

            pw.close();
        }

        public static void SolveSingleProblem() throws IOException{

            long n = sc.nextLong();

            long dig = (long)Math.log10(n) + 1;

            long mirr = n;

            String s = "";
            for(int i =0; i < dig + 1; i++)
                s+="1";

            long k = Long.parseLong(s);

            long k2 = Long.parseLong(s.substring(1));

            long answ1 = best(n, k);

            long answ2 = best(n, k2);

            answ1 = min(answ1, answ2);

            pw.println(answ1);
        }

        static long best(long n, long k){

            if(k == 1) return n;

            int cumul = 0;
            int digits = (int)Math.log10(k) + 1;

            if(n == k){
                long ret = digits;
                return ret;
            }

            if(k < n){

                long ret = digits + best(n - k , k);
                return ret;
            }

            long left = digits + best( k - n, k / 10);

            long right = best(n, k / 10);

            return min(left, right);
        }

        static long min(long a, long b){
            return (a < b)? a: b;
        }

    }

    class MyScanner{
        BufferedReader br;
        StringTokenizer stk;
        public MyScanner(InputStream stream){
            this.br = new BufferedReader(new InputStreamReader(stream),72357);
            this.stk = new StringTokenizer("");
        }
        public MyScanner(FileReader fr){
            this.br = new BufferedReader(fr);
            this.stk = new StringTokenizer("");
        }
        public String next() throws IOException {
            while(!stk.hasMoreElements()){
                String line = br.readLine();
                if(line == null)
                    return null;
                stk = new StringTokenizer(line);
            }
            return stk.nextToken();
        }
        public int nextInt()throws IOException{
            return Integer.parseInt(next());
        }

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

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

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

    class MyWriter{
        PrintWriter pw;
        public MyWriter(OutputStream out){
            this.pw = new PrintWriter(out);
        }
        public void print(Object obj){
            pw.print(obj.toString());
        }
        public void println(Object obj){
            pw.println(obj.toString());
        }
        public void close() {
            pw.close();
        }
    }