description: Berland Music is a music streaming service built specifically to support Berland local artist. Its developers are currently working on a song recommendation module.
  
  So imagine Monocarp got recommended n songs, numbered from 1 to n. The i-th song had its predicted rating equal to p_i, where 1 ≤ p_i ≤ n and every integer from 1 to n appears exactly once. In other words, p is a permutation.
  
  After listening to each of them, Monocarp pressed either a like or a dislike button. Let his vote sequence be represented with a string s, such that s_i=0 means that he disliked the i-th song, and s_i=1 means that he liked it.
  
  Now the service has to re-evaluate the song ratings in such a way that:
  
    * the new ratings q_1, q_2, ..., q_n still form a permutation (1 ≤ q_i ≤ n; each integer from 1 to n appears exactly once); 
    * every song that Monocarp liked should have a greater rating than every song that Monocarp disliked (formally, for all i, j such that s_i=1 and s_j=0, q_i>q_j should hold). 
  
  
  
  Among all valid permutations q find the one that has the smallest value of ∑_{i=1}^n |p_i-q_i|, where |x| is an absolute value of x.
  
  Print the permutation q_1, q_2, ..., q_n. If there are multiple answers, you can print any of them.
  
  Input
  
  The first line contains a single integer t (1 ≤ t ≤ 10^4) — the number of testcases.
  
  The first line of each testcase contains a single integer n (1 ≤ n ≤ 2 ⋅ 10^5) — the number of songs.
  
  The second line of each testcase contains n integers p_1, p_2, ..., p_n (1 ≤ p_i ≤ n) — the permutation of the predicted ratings.
  
  The third line contains a single string s, consisting of n characters. Each character is either a 0 or a 1. 0 means that Monocarp disliked the song, and 1 means that he liked it.
  
  The sum of n over all testcases doesn't exceed 2 ⋅ 10^5.
  
  Output
  
  For each testcase, print a permutation q — the re-evaluated ratings of the songs. If there are multiple answers such that ∑_{i=1}^n |p_i-q_i| is minimum possible, you can print any of them.
  
  Example
  
  Input
  
  
  3
  2
  1 2
  10
  3
  3 1 2
  111
  8
  2 3 1 8 5 4 7 6
  01110001
  
  
  Output
  
  
  2 1
  3 1 2
  1 6 5 8 3 2 4 7
  
  Note
  
  In the first testcase, there exists only one permutation q such that each liked song is rating higher than each disliked song: song 1 gets rating 2 and song 2 gets rating 1. ∑_{i=1}^n |p_i-q_i|=|1-2|+|2-1|=2.
  
  In the second testcase, Monocarp liked all songs, so all permutations could work. The permutation with the minimum sum of absolute differences is the permutation equal to p. Its cost is 0.
solution: 
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.PrintWriter; // System.out is a PrintStream
  import java.util.InputMismatchException;
  import java.util.PriorityQueue;
  
  
  public class B {
      private static int MOD = (int)1e9 + 7, mod = 99_82_44_353;
      private static double PI = 3.14159265358979323846;
  
      public static void main(String[] args) throws IOException {
          FasterScanner scn = new FasterScanner();
          PrintWriter out = new PrintWriter(System.out);
          for (int tc = scn.nextInt(); tc > 0; tc--) {
              int N = scn.nextInt(), curr = N;
              int[] arr = new int[N];
              for (int i = 0; i < N; i++) {
                  arr[i] = scn.nextInt();
              }
              char[] str = scn.next().toCharArray();
              PriorityQueue<int[]> pq0 = new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : b[0] - a[0])
                                 , pq1 = new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : b[0] - a[0]);
              for (int i = 0; i < N; i++) {
                  if (str[i] == '0') {
                      pq0.add(new int[] { arr[i], i });
                  } else {
                      pq1.add(new int[] { arr[i], i });
                  }
              }
              while (pq1.size() > 0) {
                  int[] tp = pq1.remove();
                  arr[tp[1]] = curr--;
              }
              while (pq0.size() > 0) {
                  int[] tp = pq0.remove();
                  arr[tp[1]] = curr--;
              }
              for (int i = 0; i < N; i++) {
                  out.print(arr[i] + " ");
              }
              out.println();
          }
          out.close();
      }
  
      /* ------------------- Sorting ------------------- */
      private static void ruffleSort(int[] arr) {
          // int N = arr.length;
          // Random rand = new Random();
          // for (int i = 0; i < N; i++) {
          //     int oi = rand.nextInt(N), temp = arr[i];
          //     arr[i] = arr[oi];
          //     arr[oi] = temp;
          // }
          // Arrays.sort(arr);
      }
          
      /* ------------------- Sorting ------------------- */
      
      private static boolean isPalindrome(String str) {
          for (int i = 0, j = str.length() - 1; i < j; i++, j--) {
              if (str.charAt(i) != str.charAt(j)) {
                  return false;
              }
          }
          return true;
      }
      
      private static boolean isPalindrome(char[] str) {
          for (int i = 0, j = str.length - 1; i < j; i++, j--) {
              if (str[i] != str[j]) {
                  return false;
              }
          }
          return true;
      }
      
      /* ------------------- Pair class ------------------- */
      private static class Pair implements Comparable<Pair> {
  		int x, y;
  		Pair(int x, int y) {
  			this.x = x;
  			this.y = y;
  		}
  		public int compareTo(Pair o) {
  			return this.x == o.x ? this.y - o.y : this.x - o.x;
  		}
  	}
  
      /* ------------------- HCF and LCM ------------------- */
      private static int gcd(int num1, int num2) {
          int temp = 0;
          while (num2 != 0) {
              temp = num1;
              num1 = num2;
              num2 = temp % num2;
          }
          return num1;
      }
      
      private static int lcm(int num1, int num2) {
          return (int)((1L * num1 * num2) / gcd(num1, num2));
      }
      
      /* ------------------- primes and prime factorization ------------------- */
      private static boolean[] seive(int N) {
          // true means not prime, false means is a prime number :)
          boolean[] notPrimes = new boolean[N + 1];
          notPrimes[0] = notPrimes[1] = true;
          for (int i = 2; i * i <= N; i++) {
              if (notPrimes[i]) continue;
              for (int j = i * i; j <= N; j += i) {
                  notPrimes[j] = true;
              }
          }
          return notPrimes;
      }
  
  	/*
      private static TreeMap<Integer, Integer> primeFactors(long N) {
  		TreeMap<Integer, Integer> primeFact = new TreeMap<>();
  		for (int i = 2; i <= Math.sqrt(N); i++) {
              int count = 0;
              while (N % i == 0) {
                  N /= i;
                  count++;
              }
              if (count != 0) {
                  primeFact.put(i, count);
              }
  		}
  		if (N != 1) {
              primeFact.put((int)N, 1);
          }
  		return primeFact;
  	}
      */
  
      /* ------------------- Binary Search ------------------- */
      private static long factorial(int N) {
          long ans = 1L;
          for (int i = 2; i <= N; i++) {
              ans *= i;
          }
          return ans;
      }
  
      private static long[] factorialDP(int N) {
          long[] factDP = new long[N + 1];
          factDP[0] = factDP[1] = 1;
          for (int i = 2; i <= N; i++) {
              factDP[i] = factDP[i - 1] * i;
          }
          return factDP;
      }
  
      private static long factorialMod(int N, int mod) {
          long ans = 1L;
          for (int i = 2; i <= N; i++) {
              ans = ((ans % mod) * (i % mod)) % mod;
          }
          return ans;
      }
  
      /* ------------------- Binary Search ------------------- */
      private static int floorSearch(int[] arr, int st, int ed, int tar) {
          int ans = -1;
          while (st <= ed) {
              int mid = ((ed - st) >> 1) + st;
              if (arr[mid] <= tar) {
                  ans = mid;
                  st = mid + 1;
              } else {
                  ed = mid - 1;
              }
          }
          return ans;
      }
      
      private static int ceilingSearch(int[] arr, int st, int ed, int tar) {
          int ans = -1;
          while (st <= ed) {
              int mid = ((ed - st) >> 1) + st;
              if (arr[mid] < tar) {
                  st = mid + 1;
              } else {
                  ans = mid;
                  ed = mid - 1;
              }
          }
          return ans;
      }
      
      /* ------------------- Power Function ------------------- */
      public static long pow(long x, long y) {
          long res = 1;
  		while (y > 0) {
              if ((y & 1) != 0) {
                  res = (res * x);
  				y--;
  			}
  			x = (x * x);
  			y >>= 1;
  		}
  		return res;
  	}
      
  	public static long powMod(long x, long y, int mod) {
          long res = 1;
  		while (y > 0) {
              if ((y & 1) != 0) {
                  res = (res * x) % mod;
  				y--;
  			}
  			x = (x * x) % mod;
  			y >>= 1;
  		}
  		return res % mod;
  	}
  
      /* ------------------- Disjoint Set(Union and Find) ------------------- */
      private static class DSU {
  		public int[] parent, rank;
  		DSU(int N) {
  			parent = new int[N];
  			rank = new int[N];
  			for (int i = 0; i < N; i++) {
  				parent[i] = i;
                  rank[i] = 1;
              }
  		}
  		public int find(int a) {
  			if (parent[a] == a) {
  				return a;
              }
              return parent[a] = find(parent[a]);
  		}
  		public boolean union(int a, int b) {
  			int parA = find(a), parB = find(b);
  			if (parA == parB) return false;
  			if (rank[parA] > rank[parB]) {
                  parent[parB] = parA;
              } else if (rank[parA] < rank[parB]) {
                  parent[parA] = parB;
              } else {
                  parent[parA] = parB;
                  rank[parB]++;
              }
              return true;
  		}
  	}
      
      /* ------------------- Scanner class for input ------------------- */
      
      private static class FasterScanner {
  		private InputStream stream;
  		private byte[] buffer = new byte[1024];
  		private int curChar, numChars;
  		private SpaceCharFilter filter;
  
  		public FasterScanner() {
              // default
  			this.stream = System.in;
  		}
  
  		public FasterScanner(InputStream stream) {
  			this.stream = stream;
  		}
  
  		private int readChar() {
  			if (numChars == -1) {
  				throw new InputMismatchException();
              }
  			if (curChar >= numChars) {
  				curChar = 0;
  				try {
  					numChars = stream.read(buffer);
  				} catch (IOException e) {
  					throw new InputMismatchException(e.getMessage());
  				}
  				if (numChars <= 0) {
  					return -1;
                  }
  			}
  			return buffer[curChar++];
  		}
  
  		private boolean isWhiteSpace(int c) {
  			if (filter != null) {
  				return filter.isWhiteSpace(c);
              }
  			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
  		}
  
  		private boolean isNewLine(int ch) {
  			if (filter != null) {
  				return filter.isNewLine(ch);
              }
  			return ch == '\r' || ch == '\n' || ch == -1;
  		}
  
          public char nextChar() {
              int ch = readChar();
              char res = '\0';
              while (isWhiteSpace(ch)) {
                  ch = readChar();
              }
              do {
                  res = (char)ch;
                  ch = readChar();
              } while (!isWhiteSpace(ch));
              return res;
          }
  
  		public String next() {
  			int ch = readChar();
              StringBuilder res = new StringBuilder();
  			while (isWhiteSpace(ch)) {
  				ch = readChar();
              }
  			do {
  				res.appendCodePoint(ch);
  				ch = readChar();
  			} while (!isWhiteSpace(ch));
  			return res.toString();
  		}
  
  		public String nextLine() {
  			int ch = readChar();
              StringBuilder res = new StringBuilder();
  			do {
  				res.appendCodePoint(ch);
  				ch = readChar();
  			} while (!isNewLine(ch));
  			return res.toString();
  		}
  
  		public int nextInt() {
  			int ch = -1, sgn = 1, res = 0;
              do {
                  ch = readChar();
              } while (isWhiteSpace(ch));
  			if (ch == '-') {
  				sgn = -1;
  				ch = readChar();
  			}
  			do {
  				if (ch < '0' || ch > '9') {
  					throw new InputMismatchException("not a number");
                  }
  				res = (res * 10) + (ch - '0');
  				ch = readChar();
  			} while (!isWhiteSpace(ch));
              
  			return res * sgn;
  		}
  
  		public long nextLong() {
  			int ch = -1, sgn = 1;
              long res = 0L;
              do {
                  ch = readChar();
              } while (isWhiteSpace(ch));
  			if (ch == '-') {
  				sgn = -1;
  				ch = readChar();
  			}
  			do {
  				if (ch < '0' || ch > '9') {
  					throw new InputMismatchException("not a number");
                  }
  				res = (10L * res) + (ch - '0');
  				ch = readChar();
  			} while (!isWhiteSpace(ch));
  
  			return 1L * res * sgn;
  		}
  
          public double nextDouble() {
              return Double.parseDouble(next());
          }
  
          /* for custom delimiters */
  		public interface SpaceCharFilter {
  			public boolean isWhiteSpace(int ch);
  			public boolean isNewLine(int ch);
  		}
  	}
  }
  