Problem: The ICM ACPC World Finals is coming! Unfortunately, the organizers of the competition were so busy preparing tasks that totally missed an important technical point — the organization of electricity supplement for all the participants workstations.

There are n computers for participants, the i-th of which has power equal to positive integer pi. At the same time there are m sockets available, the j-th of which has power euqal to positive integer sj. It is possible to connect the i-th computer to the j-th socket if and only if their powers are the same: pi = sj. It is allowed to connect no more than one computer to one socket. Thus, if the powers of all computers and sockets are distinct, then no computer can be connected to any of the sockets. 

In order to fix the situation professor Puch Williams urgently ordered a wagon of adapters — power splitters. Each adapter has one plug and one socket with a voltage divider between them. After plugging an adapter to a socket with power x, the power on the adapter's socket becomes equal to <image>, it means that it is equal to the socket's power divided by two with rounding up, for example <image> and <image>.

Each adapter can be used only once. It is possible to connect several adapters in a chain plugging the first to a socket. For example, if two adapters are plugged one after enother to a socket with power 10, it becomes possible to connect one computer with power 3 to this socket.

The organizers should install adapters so that it will be possible to supply with electricity the maximum number of computers c at the same time. If there are several possible connection configurations, they want to find the one that uses the minimum number of adapters u to connect c computers.

Help organizers calculate the maximum number of connected computers c and the minimum number of adapters u needed for this.

The wagon of adapters contains enough of them to do the task. It is guaranteed that it's possible to connect at least one computer.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 200 000) — the number of computers and the number of sockets.

The second line contains n integers p1, p2, ..., pn (1 ≤ pi ≤ 109) — the powers of the computers. 

The third line contains m integers s1, s2, ..., sm (1 ≤ si ≤ 109) — the power of the sockets. 

Output

In the first line print two numbers c and u — the maximum number of computers which can at the same time be connected to electricity and the minimum number of adapters needed to connect c computers.

In the second line print m integers a1, a2, ..., am (0 ≤ ai ≤ 109), where ai equals the number of adapters orginizers need to plug into the i-th socket. The sum of all ai should be equal to u.

In third line print n integers b1, b2, ..., bn (0 ≤ bi ≤ m), where the bj-th equals the number of the socket which the j-th computer should be connected to. bj = 0 means that the j-th computer should not be connected to any socket. All bj that are different from 0 should be distinct. The power of the j-th computer should be equal to the power of the socket bj after plugging in abj adapters. The number of non-zero bj should be equal to c.

If there are multiple answers, print any of them.

Examples

Input

2 2
1 1
2 2


Output

2 2
1 1
1 2


Input

2 1
2 100
99


Output

1 6
6
1 0

Solution (in JAVA):

Solution:
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

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

  static class TaskE {
    static final int MAXNODE = 200000 * 20;
    int n;
    Computer[] computers;
    int m;
    int uniqueM;
    int[] s;
    int[] uniqueS;
    int[] disS;
    int[] idxInTrie;
    Trie trie;
    DirectedGraph graph;
    int c;
    int u;
    int[] a;
    int[] b;

    public void solve(int testNumber, QuickScanner in, QuickWriter out) {
      n = in.nextInt();
      m = in.nextInt();

      computers = new Computer[n];
      for (int i = 0; i < n; ++i) computers[i] = new Computer(in.nextInt(), i);
      Arrays.sort(computers);

      s = in.nextInt(m);
      uniqueS = Arrays.copyOf(s, m);
      Arrays.sort(uniqueS);
      uniqueM = IntArrayUtils.unique(uniqueS);
      disS = new int[m];
      idxInTrie = new int[m];
      trie = new Trie(2, MAXNODE);
      graph = new DirectedGraph(m, m);
      for (int i = 0; i < m; ++i) {
        disS[i] = IntArrayUtils.lowerBound(uniqueS, 0, uniqueM, s[i]);
        idxInTrie[i] = trie.add(s[i], disS[i]);
        graph.add(disS[i], i);
      }

      a = new int[m];
      b = new int[n];
      c = u = 0;
      for (int i = 0; i < n; ++i) {
        Computer computer = computers[i];
        int trieIdx = trie.access(computer.power);
        if (trieIdx < 0 || trie.nearestIdx[trieIdx] < 0) continue;
        int uniqueS = trie.nearestIdx[trieIdx];
        int edgeIdx = graph.lastOut[uniqueS];
        graph.lastOut[uniqueS] = graph.nextOut[edgeIdx];
        int sIdx = graph.toIdx[edgeIdx];
        b[computer.idx] = sIdx + 1;
        ++c;
        a[sIdx] = trie.nearest[trieIdx];
        u += a[sIdx];
        trie.dec(idxInTrie[sIdx]);
      }
      out.println(c, u);
      out.println(a);
      out.println(b);
    }

    class Trie extends AbstractTrie {
      final int MAXN = 40;
      int[] cnt;
      int[] nearest;
      int[] nearestIdx;
      int[] tmp = new int[MAXN];

      public Trie(int letterCapacity, int nodeCapacity) {
        super(letterCapacity, nodeCapacity);
      }


      public void create(int letterCapacity, int nodeCapacity) {
        cnt = new int[nodeCapacity];
        nearest = new int[nodeCapacity];
        nearestIdx = new int[nodeCapacity];
      }


      public void initNode(int idx, int parent, int parentLetter) {
        cnt[idx] = 0;
        nearest[idx] = MAXN;
        nearestIdx[idx] = -1;
      }

      public int add(int s, int uniqueS) {
        int len = parse(s);
        int res = add(tmp, 0, len);
        ++cnt[res];
        for (int i = res, j = 0; i >= 0; i = parent[i], ++j)
          if (nearest[i] > j) {
            nearest[i] = j;
            nearestIdx[i] = uniqueS;
          }
        return res;
      }

      public int access(int s) {
        int len = parse(s);
        return access(tmp, 0, len);
      }

      public void dec(int idx) {
        if (cnt[idx] <= 0) throw new IllegalArgumentException();
        --cnt[idx];
        for (; idx >= 0 && cnt[idx] == 0; idx = parent[idx]) {
          merge(idx);
        }
      }

      private int parse(int s) {
        int res = 0;
        for (; s > 1; s = (s + 1) >> 1) {
          tmp[res++] = 1 - (s & 1);
        }
        IntArrayUtils.reverse(tmp, 0, res);
        return res;
      }

      private void merge(int idx) {
        int left = child[0][idx], right = child[1][idx];
        if (left < 0 && right < 0) {
          nearest[idx] = MAXN;
          nearestIdx[idx] = -1;
        } else if (left < 0) {
          update(idx, right);
        } else if (right < 0) {
          update(idx, left);
        } else {
          update(idx, nearest[left] < nearest[right] ? left : right);
        }
      }

      private void update(int idx, int fromIdx) {
        nearest[idx] = Math.min(nearest[fromIdx] + 1, MAXN);
        nearestIdx[idx] = nearestIdx[fromIdx];
      }

    }

    class Computer implements Comparable<Computer> {
      int power;
      int idx;

      public Computer(int power, int idx) {
        this.power = power;
        this.idx = idx;
      }


      public int compareTo(Computer o) {
        return o.power - power;
      }

    }

  }

  static abstract class AbstractTrie {
    public int[] parent;
    public int[] parentLetter;
    public int[][] child;
    public int root;
    public int letterCnt;
    public int nodePnt;

    public abstract void create(int letterCapacity, int nodeCapacity);

    public abstract void initNode(int idx, int parent, int parentLetter);

    public AbstractTrie(int letterCapacity, int nodeCapacity) {
      parent = new int[nodeCapacity];
      parentLetter = new int[nodeCapacity];
      child = new int[letterCapacity][nodeCapacity];
      create(letterCapacity, nodeCapacity);
      init(letterCapacity);
    }

    public void init(int letterCnt) {
      this.root = 0;
      this.letterCnt = letterCnt;
      this.nodePnt = 1;
      initNodeInternal(0, -1, -1);
    }

    public int add(int[] letters, int fromIdx, int toIdx) {
      int resIdx = root;
      for (int i = fromIdx; i < toIdx; ++i) {
        int letter = letters[i];
        if (child[letter][resIdx] < 0) {
          child[letter][resIdx] = nodePnt;
          initNodeInternal(nodePnt++, resIdx, letter);
        }
        resIdx = child[letter][resIdx];
      }
      return resIdx;
    }

    public int access(int[] letters, int fromIdx, int toIdx) {
      int resIdx = root;
      for (int i = fromIdx; i < toIdx; ++i) {
        resIdx = child[letters[i]][resIdx];
        if (resIdx < 0) return resIdx;
      }
      return resIdx;
    }

    private void initNodeInternal(int idx, int parent, int letter) {
      this.parent[idx] = parent;
      this.parentLetter[idx] = letter;
      for (int i = 0; i < letterCnt; ++i) {
        child[i][idx] = -1;
      }
      initNode(idx, parent, letter);
    }

  }

  static class QuickWriter {
    private final PrintWriter writer;

    public QuickWriter(OutputStream outputStream) {
      this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

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

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

    public void println(Object... objects) {
      print(objects);
      writer.print('\n');
    }

    public void print(int[] objects) {
      print(objects, ' ');
    }

    public void print(int[] objects, char delimiter) {
      for (int i = 0; i < objects.length; ++i) {
        if (i > 0) {
          writer.print(delimiter);
        }
        writer.print(objects[i]);
      }
    }

    public void println(int[] objects) {
      print(objects);
      writer.print('\n');
    }

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

  }

  static class IntArrayUtils {
    public static void reverse(int[] values, int fromIdx, int toIdx) {
      for (int i = fromIdx, j = toIdx - 1; i < j; ++i, --j) {
        values[i] ^= values[j];
        values[j] ^= values[i];
        values[i] ^= values[j];
      }
    }

    public static int unique(int[] values) {
      return unique(values, 0, values.length);
    }

    public static int unique(int[] values, int fromIdx, int toIdx) {
      if (fromIdx == toIdx) return 0;
      int res = 1;
      for (int i = fromIdx + 1; i < toIdx; ++i) {
        if (values[i - 1] != values[i]) {
          values[fromIdx + res++] = values[i];
        }
      }
      return res;
    }

    public static int lowerBound(int[] values, int fromIdx, int toIdx, int value) {
      int res = toIdx;
      for (int lower = fromIdx, upper = toIdx - 1; lower <= upper; ) {
        int medium = (lower + upper) >> 1;
        if (value <= values[medium]) {
          res = medium;
          upper = medium - 1;
        } else {
          lower = medium + 1;
        }
      }
      return res;
    }

  }

  static class QuickScanner {
    private static final int BUFFER_SIZE = 1024;
    private InputStream stream;
    private byte[] buffer;
    private int currentPosition;
    private int numberOfChars;

    public QuickScanner(InputStream stream) {
      this.stream = stream;
      this.buffer = new byte[BUFFER_SIZE];
      this.currentPosition = 0;
      this.numberOfChars = 0;
    }

    public int nextInt() {
      int c = nextNonSpaceChar();
      boolean positive = true;
      if (c == '-') {
        positive = false;
        c = nextChar();
      }
      int res = 0;
      do {
        if (c < '0' || '9' < c) throw new RuntimeException();
        res = res * 10 + c - '0';
        c = nextChar();
      } while (!isSpaceChar(c));
      return positive ? res : -res;
    }

    public int[] nextInt(int n) {
      int[] res = new int[n];
      nextInt(n, res);
      return res;
    }

    public void nextInt(int n, int[] res) {
      for (int i = 0; i < n; ++i) {
        res[i] = nextInt();
      }
    }

    public int nextNonSpaceChar() {
      int res = nextChar();
      for (; isSpaceChar(res) || res < 0; res = nextChar()) ;
      return res;
    }

    public int nextChar() {
      if (numberOfChars == -1) {
        throw new RuntimeException();
      }
      if (currentPosition >= numberOfChars) {
        currentPosition = 0;
        try {
          numberOfChars = stream.read(buffer);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        if (numberOfChars <= 0) {
          return -1;
        }
      }
      return buffer[currentPosition++];
    }

    public boolean isSpaceChar(int c) {
      return c == ' '
          || c == '\n'
          || c == '\r'
          || c == '\t'
          || c < 0;
    }

  }

  static class DirectedGraph {
    public int vertexCnt;
    public int edgeCnt;
    public int[] fromIdx;
    public int[] toIdx;
    public int[] nextIn;
    public int[] nextOut;
    public int[] lastIn;
    public int[] lastOut;
    public int[] inDegree;
    public int[] outDegree;

    public DirectedGraph(int vertexCapacity, int edgeCapacity) {
      create(vertexCapacity, edgeCapacity);
      init(vertexCapacity);
    }

    public void create(int vertexCapacity, int edgeCapacity) {
      fromIdx = new int[edgeCapacity];
      toIdx = new int[edgeCapacity];
      lastIn = new int[vertexCapacity];
      lastOut = new int[vertexCapacity];
      nextIn = new int[edgeCapacity];
      nextOut = new int[edgeCapacity];
      inDegree = new int[vertexCapacity];
      outDegree = new int[vertexCapacity];
    }

    public void init(int vertexCnt) {
      this.vertexCnt = vertexCnt;
      this.edgeCnt = 0;
      Arrays.fill(inDegree, 0, vertexCnt, 0);
      Arrays.fill(outDegree, 0, vertexCnt, 0);
      Arrays.fill(lastIn, 0, vertexCnt, -1);
      Arrays.fill(lastOut, 0, vertexCnt, -1);
    }

    public void add(int fromIdx, int toIdx) {
      this.fromIdx[edgeCnt] = fromIdx;
      this.toIdx[edgeCnt] = toIdx;
      ++outDegree[fromIdx];
      ++inDegree[toIdx];
      nextOut[edgeCnt] = lastOut[fromIdx];
      lastOut[fromIdx] = edgeCnt;
      nextIn[edgeCnt] = lastIn[toIdx];
      lastIn[toIdx] = edgeCnt;
      ++edgeCnt;
    }

  }
}