#include <bits/stdc++.h>
using namespace std;
struct TNode {
  int val;
  int left, right;
  TNode *leftChild, *rightChild;
};
TNode nodes[210100 * 2];
TNode *root;
int numNode = 0;
TNode *newNode(int val, int left, int right) {
  TNode *newNode = &nodes[numNode];
  numNode++;
  newNode->val = val;
  newNode->left = left;
  newNode->right = right;
  newNode->leftChild = NULL;
  newNode->rightChild = NULL;
  return newNode;
}
void buildSegmentTree(TNode **node, int left, int right) {
  int val = (right - left) + 1;
  int mid = (left + right) / 2;
  (*node) = newNode(val, left, right);
  if (left == right) return;
  buildSegmentTree(&(*node)->leftChild, left, mid);
  buildSegmentTree(&(*node)->rightChild, mid + 1, right);
}
void resetSegmentTree(int n) {
  numNode = 0;
  root = &nodes[0];
  buildSegmentTree(&root, 0, n - 1);
}
int querySegmentTree(TNode *node, int left, int right) {
  if (node->left == left && node->right == right) return node->val;
  int mid = (node->left + node->right) / 2;
  if (left > mid) return querySegmentTree(node->rightChild, left, right);
  if (right <= mid) return querySegmentTree(node->leftChild, left, right);
  return querySegmentTree(node->leftChild, left, mid) +
         querySegmentTree(node->rightChild, mid + 1, right);
}
int getNodeValue(TNode *node) {
  if (node == NULL) return 0;
  return node->val;
}
int querySegmentTreeByVal(TNode *node, int val) {
  if (node->left == node->right) return node->right;
  assert(node != NULL);
  int leftValue = getNodeValue(node->leftChild);
  if (leftValue >= val) return querySegmentTreeByVal(node->leftChild, val);
  return querySegmentTreeByVal(node->rightChild, val - leftValue);
}
int updateSegmentTree(TNode *node, int key, int value) {
  int left = node->left;
  int right = node->right;
  int mid = (left + right) / 2;
  if (left == right && left == key) {
    node->val = value;
  } else if (key <= mid) {
    node->val = updateSegmentTree(node->leftChild, key, value) +
                querySegmentTree(node, mid + 1, right);
  } else if (key > mid) {
    node->val = updateSegmentTree(node->rightChild, key, value) +
                querySegmentTree(node, left, mid);
  }
  return node->val;
}
int findElementLessThenOrEqX(int x) { return querySegmentTree(root, 0, x); }
int findKthElement(int k) { return querySegmentTreeByVal(root, k); }
void removeXFromList(int x) { updateSegmentTree(root, x, 0); }
int n;
int a[210100];
int b[210100];
int ordA[210100];
int ordB[210100];
void readAndStore(int *arr, int n) {
  for (int i = 0; i < n; i++) {
    scanf("%d", &arr[i]);
  }
}
void readInput() {
  scanf("%d", &n);
  readAndStore(a, n);
  readAndStore(b, n);
}
void findOrd(int *arr, int *ordArr, int n) {
  resetSegmentTree(n);
  for (int i = 0; i < n; i++) {
    int restOfAllElement = n - i - 1;
    int lesserElNum = findElementLessThenOrEqX(arr[i]) - 1;
    ordArr[restOfAllElement] = lesserElNum;
    removeXFromList(arr[i]);
  }
}
int *sumOrdAndStoreInX(int *x, int *y, int n) {
  for (int i = 0; i < n; i++) {
    x[i] += y[i];
    if (x[i] >= i + 1) {
      x[i + 1] += x[i] / (i + 1);
      x[i] %= (i + 1);
    }
  }
  return x;
}
void solve() {
  findOrd(a, ordA, n);
  findOrd(b, ordB, n);
  int *ord = sumOrdAndStoreInX(ordA, ordB, n);
  resetSegmentTree(n);
  for (int i = n - 1; i >= 0; i--) {
    int val = ord[i] + 1;
    int kthEl = findKthElement(val);
    removeXFromList(kthEl);
    printf("%d%c", kthEl, i == 0 ? '\n' : ' ');
  }
}
int main() {
  readInput();
  solve();
  return 0;
}
