import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string rstring(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T rtype(T)(){ return rstring.to!T; } alias rint = rtype!int, rlong = rtype!long, rreal = rtype!real;
T[] rtypes(T)(int n){ return n.iota.map!(i => rtype!T()).array; } alias rint = rtypes!int, rlong = rtypes!long, rreal = rtypes!real;
T[][] rtypess(T)(int n, int m){ return n.iota.map!(i => rtypes!T(m)).array; } alias rint = rtypess!int, rlong = rtypess!long, rreal = rtypess!real;
T chmin(T)(ref T x, T y){ if(x > y) x = y; return x; } T chmax(T)(ref T x, T y){ if(x < y) x = y; return x; }

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int m = rint, n = rint, k = rint, t = rint;
	long[] as = rlong(m);
	as.sort!"a>b"();

	X[] traps;
	foreach(i; 0 .. k) traps ~= X(rint, rint, rlong);

	bool isOK(int x){
		long a = (x > 0? as[x - 1]: 200_999);
		int[] ls, rs;
		foreach(tr; traps) if(tr.d > a) ls ~= tr.l, rs ~= tr.r;
		ls.sort(), rs.sort();
		auto lq = new Queue!int(ls), rq = new Queue!int(rs);
		int leftpos = 0;
		int time = (n + 1);
		int cnt = 0;
		log("x:", x, "a:", a, "ls:", ls, "rs:", rs, "lq:", lq, "rq:", rq, "leftpos:", leftpos, "cnt:", cnt, "time:", time);
		while(lq.length + rq.length > 0){
			if(lq.length > 0 && lq.peek <= rq.peek){
				if(cnt == 0) leftpos = lq.peek - 1;
				lq.deq, cnt += 1;
			}
			else{
				if(cnt == 1) time += (rq.peek - leftpos) * 2;
				rq.deq, cnt -= 1;
			}
			log("lq:", lq, "rq:", rq, "leftpos:", leftpos, "cnt:", cnt, "time:", time);
		}
//		log("x:", x, "a:", a, "leftend:", leftend, "rightend:", rightend, "time:", time, "isOK:", time <= t);
		return time <= t;

	}

	int ans = uplimit(0, m, &isOK);
	ans.writeln;
}
struct X{
	int l, r;
	long d;
}
// 二分探索テンプレート
T uplimit(T)(T a, T c, bool delegate(T) f){
	if(f(c)) return c; if(! f(a)) return a - 1;
	while(a + 1 < c){ T b = (a + c) / 2; if(f(b)) a = b; else c = b; }
	return a;
}
T downlimit(T)(T a, T c, bool delegate(T) f){
	if(f(a)) return a; if(! f(c)) return c + 1;
	while(a + 1 < c){ T b = (a + c) / 2; if(f(b)) c = b; else a = b; }
	return c;
}
// ----- キュー -----
class Queue(T){
	private T[] xs;
	private uint i, j; // i : 次に読み出す位置　j: 次に書き込む位置
	this(){	}
	this(T[] xs){ this.xs = xs; j = xs.length; }
	void enq(T x){
		while(j + 1 >= xs.length) xs.length = xs.length * 2 + 1;
		xs[j ++] = x;
	}
	ulong length(){ return j - i; }
	bool isEmpty(){ return j == i; }
	T deq(){ assert(i < j); return xs[i ++]; }
	T peek(){ assert(i < j); return xs[i]; }
	T[] array(){ return xs[i .. j]; }
	override string toString(){ return array.to!string; }
}
/*
5 6 4 14
1 2 3 4 5
1 5 2
1 2 5
3 4 5
3 5 3
*/

import std.algorithm;
import std.range;
import std.stdio;
import std.typecons;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
    	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;
int main()
{
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  r(a);
  alias Trap = Tuple!(int, "right", int, "danger");
  Trap[][] pos;
  pos.length = n + 2;
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Trap(right, danger);
    }
  bool can(int ag)
  {
    if (ag <= 0) return true;
    int ct = 0;
    for(int i = 0; i < n + 1;)
      {
	int j, objective = i + 1;
	bool deact = false;
	for(j = i + 1; j <= objective; j++)
	    foreach(cell; pos[j])
	      if(cell.danger > ag)
		objective = max(objective, cell.right), deact = true;
	ct += (objective - i) * (1 + 2 * deact);
	if (ct > t) return false;
	i = objective;
      }
    return true;
  }
  auto ag = iota(1, 200000 + 1).assumeSorted!((a, b) => !can(a) && can(b)).equalRange(0)[0];
  auto sortedA = sort!"a < b"(a);
  w(sortedA.upperBound(ag).length + sortedA.equalRange(ag).length);
  return 0;
}

import std.stdio;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
    	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;

struct Cell
{
  int right, danger;
  this(bool active, int right, int danger)
  {
    this.right = right;
    this.danger = danger;
  }
}

int main()
{
  import std.container.rbtree;
  import std.algorithm;
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  Cell[][] pos;
  int[][] deact;
  pos.length = n + 2;
  deact.length = n + 2;
  r(a);
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Cell(true, right, danger);
      deact[right] ~= l;
    }
  bool can(int ag)
  {
    int pa = 0;
    int pm = 0;
    int ct = 0;
    bool[] active;
    active.length = n + 2;
    active[] = true;
    while(pa != n + 1)
      {
    	int obj = 0;
    	while(true)
    	  {
    	    bool mustbreak = false;
    	    foreach(cell; pos[pm + 1])
    	      {
    		if (active[pm + 1] && cell.danger > ag)
    		  {
    		    mustbreak = true;
    		    obj = max(obj, cell.right);
    		  }
    	      }
    	    if (mustbreak)
    	      break;
    	    pm++;
    	    pa++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	    if (pa == n + 1)
    	      {
    		return true;
    	      }
    	  }

    	for(; pm <= obj;)
    	  {
    	    foreach(d; deact[pm])
    	      {
    		active[d] = false;
    	      }
    	    foreach(cell; pos[pm])
    	      {
    		if (active[pm] && cell.danger > ag)
    		  obj = max(obj, cell.right);
    	      }
    	    if (pm == obj)
    	      {
    		break;
    	      }
    	    pm++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	  }
    	assert(pm == obj);
    	ct += (pm - pa) * 2;
    	pa = obj;
    	if (ct > t)
    	  return false;
      }
    assert(0);
  }
  import std.range;
  auto ag = iota(1, 200000 + 1).map!((a=>cast(int)can(a))).assumeSorted.equalRange(0).length + 1;
  auto sortedA = sort!"a < b"(a);
  w(sortedA.upperBound(ag).length + sortedA.equalRange(ag).length);

  return 0;
}

import std.algorithm;
import std.range;
import std.stdio;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
    	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;

struct Cell
{
  int right, danger;
  this(int right, int danger)
  {
    this.right = right;
    this.danger = danger;
  }
}
int main()
{
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  r(a);
  Cell[][] pos;
  pos.length = n + 2;
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Cell(right, danger);
    }
  bool can(int ag)
  {
    if (ag <= 0) return true;
    int ct = 0;
    for(int i = 0; i < n + 1;)
      {
	int j, objective = i + 1;
	bool deact = false;
	for(j = i + 1; j <= objective; j++)
	    foreach(cell; pos[j])
	      if(cell.danger > ag)
		objective = max(objective, cell.right), deact = true;
	ct += (objective - i) * (1 + 2 * deact);
	if (ct > t) return false;
	i = objective;
      }
    return true;
  }
  auto ag = iota(1, 200000 + 1).assumeSorted!((a, b) => !can(a) && can(b)).equalRange(0)[0];
  auto sortedA = sort!"a < b"(a);
  w(sortedA.upperBound(ag).length + sortedA.equalRange(ag).length);
  return 0;
}

import std.stdio;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
    	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;

struct Cell
{
  int right, danger;
  this(bool active, int right, int danger)
  {
    this.right = right;
    this.danger = danger;
  }
}

int main()
{
  import std.container.rbtree;
  import std.algorithm;
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  Cell[][] pos;
  int[][] deact;
  pos.length = n + 2;
  deact.length = n + 2;
  r(a);
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Cell(true, right, danger);
      deact[right] ~= l;
    }
  bool can(int ag)
  {
    if (ag <= 0)
      return true;
    int pa = 0;
    int pm = 0;
    int ct = 0;
    bool[] active;
    active.length = n + 2;
    active[] = true;
    while(pa != n + 1)
      {
    	int obj = 0;
    	while(true)
    	  {
    	    bool mustbreak = false;
    	    foreach(cell; pos[pm + 1])
    	      {
    		if (active[pm + 1] && cell.danger > ag)
    		  {
    		    mustbreak = true;
    		    obj = max(obj, cell.right);
    		  }
    	      }
    	    if (mustbreak)
    	      break;
    	    pm++;
    	    pa++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	    if (pa == n + 1)
    	      {
    		return true;
    	      }
    	  }

    	for(; pm <= obj;)
    	  {
    	    foreach(d; deact[pm])
    	      {
    		active[d] = false;
    	      }
    	    foreach(cell; pos[pm])
    	      {
    		if (active[pm] && cell.danger > ag)
    		  obj = max(obj, cell.right);
    	      }
    	    if (pm == obj)
    	      {
    		break;
    	      }
    	    pm++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	  }
    	assert(pm == obj);
    	ct += (pm - pa) * 2;
    	pa = obj;
    	if (ct > t)
    	  return false;
      }
    assert(0);
  }
  import std.range;
  auto ag = iota(1, 200000 + 1).assumeSorted!((a, b) => !can(a) && can(b)).equalRange(0)[0];
  auto sortedA = sort!"a < b"(a);
  w(sortedA.upperBound(ag).length + sortedA.equalRange(ag).length);

  return 0;
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n, m, k, t;
    readf("%s %s %s %s", &m, &n, &k, &t);
    readln;

    auto arr = readln.chomp.split.map!(to!int).array;

    auto ds = new int[] (k);
    alias trap = Tuple!(int, bool);
    auto open = new int[][] (n+1);
    auto close = new int[][] (n+1);

    foreach (i; 0 .. k) {
        int le, r, d;
        readf("%s %s %s", &le, &r, &d);
        readln;

        ds[i] = d;
        open[le] ~= i;
        close[r] ~= i;
    }

    arr.sort();
    arr.reverse();

    bool isOk(int toBring) {

        int tot = 0;
        int threshold = arr[toBring-1];

        debug { writeln(toBring, ' ', threshold); }

        bool alone = false;
        int soldiersPos = 0;
        int trapsCnt = 0;
        foreach (i; 1 .. n+1) {
            foreach (idx; open[i]) {
                if (ds[idx] <= threshold) { continue; }

                trapsCnt += 1;
                alone = true;
            }

            foreach (idx; close[i]) {
                if (ds[idx] <= threshold) { continue; }

                trapsCnt -= 1;
            }

            if (trapsCnt == 0) {
                if (alone) { tot += 2 * (i - soldiersPos); }
                tot += i - soldiersPos;
                soldiersPos = i;
                alone = false;
            }

            debug { writeln(i, ' ', soldiersPos, ' ', tot); }
        }

        tot += 1;
        return tot <= t;
    }

    int le = 0, r = m;
    while (le < r) {
        int c = (le + r) / 2 + 1;

        if (isOk(c)) { le = c; }
        else { r = c-1; }
    }

    le.writeln;
}

import std.stdio;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
    	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;

struct Cell
{
  int right, danger;
  this(bool active, int right, int danger)
  {
    this.right = right;
    this.danger = danger;
  }
}

int main()
{
  import std.container.rbtree;
  import std.algorithm;
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  Cell[][] pos;
  int[][] deact;
  pos.length = n + 2;
  deact.length = n + 2;
  r(a);
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Cell(true, right, danger);
      deact[right] ~= l;
    }
  bool can(int ag)
  {
    int pa = 0;
    int pm = 0;
    int ct = 0;
    bool[] active;
    active.length = n + 2;
    active[] = true;
    while(pa != n + 1)
      {
    	int obj = 0;
    	while(true)
    	  {
    	    bool mustbreak = false;
    	    foreach(cell; pos[pm + 1])
    	      {
    		if (active[pm + 1] && cell.danger > ag)
    		  {
    		    mustbreak = true;
    		    obj = max(obj, cell.right);
    		  }
    	      }
    	    if (mustbreak)
    	      break;
    	    pm++;
    	    pa++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	    if (pa == n + 1)
    	      {
    		return true;
    	      }
    	  }

    	for(; pm <= obj;)
    	  {
    	    foreach(d; deact[pm])
    	      {
    		active[d] = false;
    	      }
    	    foreach(cell; pos[pm])
    	      {
    		if (active[pm] && cell.danger > ag)
    		  obj = max(obj, cell.right);
    	      }
    	    if (pm == obj)
    	      {
    		break;
    	      }
    	    pm++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	  }
    	assert(pm == obj);
    	ct += (pm - pa) * 2;
    	pa = obj;
    	if (ct > t)
    	  return false;
      }
    assert(0);
  }
  import std.range;
  auto ag = iota(1, 200000 + 1).assumeSorted!((a, b)=> cast(int)can(a) < cast(int)can(b)).upperBound(false)[0];
  auto sortedA = sort!"a < b"(a);
  w(sortedA.upperBound(ag).length + sortedA.equalRange(ag).length);

  return 0;
}

import std.stdio;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
    	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;

struct Cell
{
  int right, danger;
  this(bool active, int right, int danger)
  {
    this.right = right;
    this.danger = danger;
  }
}

int main()
{
  import std.container.rbtree;
  import std.algorithm;
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  Cell[][] pos;
  int[][] deact;
  pos.length = n + 2;
  deact.length = n + 2;
  r(a);
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Cell(true, right, danger);
      deact[right] ~= l;
    }
  bool can(int ag)
  {
    int pa = 0;
    int pm = 0;
    int ct = 0;
    bool[] active;
    active.length = n + 2;
    active[] = true;
    while(pa != n + 1)
      {
    	int obj = 0;
    	while(true)
    	  {
    	    bool mustbreak = false;
    	    foreach(cell; pos[pm + 1])
    	      {
    		if (active[pm + 1] && cell.danger > ag)
    		  {
    		    mustbreak = true;
    		    obj = max(obj, cell.right);
    		  }
    	      }
    	    if (mustbreak)
    	      break;
    	    pm++;
    	    pa++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	    if (pa == n + 1)
    	      {
    		return true;
    	      }
    	  }

    	for(; pm <= obj;)
    	  {
    	    foreach(d; deact[pm])
    	      {
    		active[d] = false;
    	      }
    	    foreach(cell; pos[pm])
    	      {
    		if (active[pm] && cell.danger > ag)
    		  obj = max(obj, cell.right);
    	      }
    	    if (pm == obj)
    	      {
    		break;
    	      }
    	    pm++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	  }
    	assert(pm == obj);
    	ct += (pm - pa) * 2;
    	pa = obj;
    	if (ct > t)
    	  return false;
      }
    assert(0);
  }
  import std.range;
  auto ag = iota(1, 10 + 1).assumeSorted!((a, b)=> cast(int)can(a) < cast(int)can(b)).upperBound(true)[0];
  auto sortedA = sort!"a < b"(a);
  w(sortedA.upperBound(ag).length + sortedA.equalRange(ag).length);

  return 0;
}

import std.stdio;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
    	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;

struct Cell
{
  int right, danger;
  this(bool active, int right, int danger)
  {
    this.right = right;
    this.danger = danger;
  }
}

int main()
{
  import std.container.rbtree;
  import std.algorithm;
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  Cell[][] pos;
  int[][] deact;
  pos.length = n + 2;
  deact.length = n + 2;
  r(a);
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Cell(true, right, danger);
      deact[right] ~= l;
    }
  bool can(int ag)
  {
    int pa = 0;
    int pm = 0;
    int ct = 0;
    bool[] active;
    active.length = n + 2;
    active[] = true;
    while(pa != n + 1)
      {
    	int obj = 0;
    	while(true)
    	  {
    	    bool mustbreak = false;
    	    foreach(cell; pos[pm + 1])
    	      {
    		if (active[pm + 1] && cell.danger > ag)
    		  {
    		    mustbreak = true;
    		    obj = max(obj, cell.right);
    		  }
    	      }
    	    if (mustbreak)
    	      break;
    	    pm++;
    	    pa++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	    if (pa == n + 1)
    	      {
    		return true;
    	      }
    	  }

    	for(; pm <= obj;)
    	  {
    	    foreach(d; deact[pm])
    	      {
    		active[d] = false;
    	      }
    	    foreach(cell; pos[pm])
    	      {
    		if (active[pm] && cell.danger > ag)
    		  obj = max(obj, cell.right);
    	      }
    	    if (pm == obj)
    	      {
    		break;
    	      }
    	    pm++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	  }
    	assert(pm == obj);
    	ct += (pm - pa) * 2;
    	pa = obj;
    	if (ct > t)
    	  return false;
      }
    assert(0);
  }
  import std.range;
  auto ag = iota(1, 200000 + 1).assumeSorted!((a, b)=> cast(int)can(a) < cast(int)can(b)).upperBound(true)[0];
  auto sortedA = sort!"a < b"(a);
  w(sortedA.upperBound(ag).length + sortedA.equalRange(ag).length);

  return 0;
}

import std.stdio;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
    	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;

struct Cell
{
  int right, danger;
  this(bool active, int right, int danger)
  {
    this.right = right;
    this.danger = danger;
  }
}

int main()
{
  import std.container.rbtree;
  import std.algorithm;
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  Cell[][] pos;
  int[][] deact;
  pos.length = n + 2;
  deact.length = n + 2;
  r(a);
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Cell(true, right, danger);
      deact[right] ~= l;
    }
  bool can(int ag)
  {
    int pa = 0;
    int pm = 0;
    int ct = 0;
    bool[] active;
    active.length = n + 2;
    active[] = true;
    while(pa != n + 1)
      {
    	int obj = 0;
    	while(true)
    	  {
    	    bool mustbreak = false;
    	    foreach(cell; pos[pm + 1])
    	      {
    		if (active[pm + 1] && cell.danger > ag)
    		  {
    		    mustbreak = true;
    		    obj = max(obj, cell.right);
    		  }
    	      }
    	    if (mustbreak)
    	      break;
    	    pm++;
    	    pa++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	    if (pa == n + 1)
    	      {
    		return true;
    	      }
    	  }

    	for(; pm <= obj;)
    	  {
    	    foreach(d; deact[pm])
    	      {
    		active[d] = false;
    	      }
    	    foreach(cell; pos[pm])
    	      {
    		if (active[pm] && cell.danger > ag)
    		  obj = max(obj, cell.right);
    	      }
    	    if (pm == obj)
    	      {
    		break;
    	      }
    	    pm++;
    	    ct++;
    	    if (ct > t)
    	      return false;
    	  }
    	assert(pm == obj);
    	ct += (pm - pa) * 2;
    	pa = obj;
    	if (ct > t)
    	  return false;
      }
    assert(0);
  }
  import std.range;
  auto ag = iota(1, 200000 + 1).assumeSorted!((a, b) => !can(a) && can(b)).equalRange(false).length + 1;
  auto sortedA = sort!"a < b"(a);
  w(sortedA.upperBound(ag).length + sortedA.equalRange(ag).length);

  return 0;
}

import std.stdio;

void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]))
      foreach(ref e; args[i])
	read(e);
    else
      readf!" %s"(args[i]);
}
alias r = read;
alias w = writeln;

struct Cell
{
  int right, danger;
  this(bool active, int right, int danger)
  {
    this.right = right;
    this.danger = danger;
  }
}

int main()
{
  import std.container.rbtree;
  import std.algorithm;
  int m, n, k, t;
  r(m, n, k, t);
  int[] a;
  a.length = m;
  Cell[][] pos;
  int[][] deact;
  pos.length = n + 2;
  deact.length = n + 2;
  r(a);
  foreach(i; 0 .. k)
    {
      int l, right, danger;
      r(l, right, danger);
      pos[l] ~= Cell(true, right, danger);
      deact[right] ~= l;
    }
  bool can(int ag)
  {
    int pa = 0;
    int pm = 0;
    int ct = 0;
    bool[] active;
    active.length = n + 2;
    active[] = true;
    while(pa != n + 1)
      {
	int obj = 0;
	while(true)
	  {
	    bool mustbreak = false;
	    foreach(cell; pos[pm + 1])
		if (active[pm + 1] && cell.danger > ag)
		  {
		    mustbreak = true;
		    obj = max(obj, cell.right);
		  }
	    if (mustbreak)
	      break;
	    pm++;
	    pa++;
	    ct++;
	    if (ct > t)
	      return false;
	    if (pa == n + 1)
		return true;
	  }

	for(; pm <= obj;)
	  {
	    foreach(d; deact[pm])
		active[d] = false;
	    foreach(cell; pos[pm])
		if (active[pm] && cell.danger > ag)
		  obj = max(obj, cell.right);
	    if (pm == obj)
		break;
	    pm++;
	    ct++;
	    if (ct > t)
	      return false;
	  }
	assert(pm == obj);
	ct += (pm - pa) * 2;
	pa = obj;
	if (ct > t)
	  return false;
      }
    assert(0);
  }
  import std.range;
  auto ag = (assumeSorted!((int a, int b) => !can(a) || can(b))(iota(1, 200000 + 1)).lowerBound(true).length + 1);
  auto sortedA = sort!"a <= b"(a);
  auto res = sortedA.upperBound(ag).length;
  w(res);

  return 0;
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n, m, k, t;
    readf("%s %s %s %s", &n, &m, &k, &t);
    readln;

    auto arr = readln.chomp.split.map!(to!int).array;

    auto ds = new int[] (k);
    auto open = new int[][] (n+1);
    auto close = new int[][] (n+1);

    foreach (i; 0 .. k) {
        int le, r, d;
        readf("%s %s %s", &le, &r, &d);
        readln;

        ds[i] = d;
        open[le] ~= i;
        close[r] ~= i;
    }

    arr.sort();
    arr.reverse();

    bool isOk(int toBring) {

        int tot = 0;
        int threshold = arr[toBring-1];

        debug { writeln(toBring, ' ', threshold); }

        bool alone = false;
        int soldiersPos = 0;
        auto onPath = new bool[] (k);
        onPath[] = false;
        int onPathCnt = 0;
        foreach (i; 1 .. n+1) {
            foreach (idx; open[i]) {
                if (ds[idx] <= threshold) { continue; }

                onPath[idx] = true;
                onPathCnt += 1;
                alone = true;
            }

            foreach (idx; close[i]) {
                if (onPath[idx]) {
                    onPath[idx] = false;
                    onPathCnt -= 1;
                }
            }

            if (onPathCnt == 0) {
                if (alone) { tot += 2 * (i - soldiersPos); }
                tot += i - soldiersPos;
                soldiersPos = i;
                alone = false;
            }

            debug { writeln(i, ' ', soldiersPos, ' ', onPath, ' ', tot); }
        }

        tot += 1;
        return tot <= t;
    }

    int le = 0, r = n;
    while (le < r) {
        int c = (le + r) / 2 + 1;

        if (isOk(c)) { le = c; }
        else { r = c-1; }
    }

    le.writeln;
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n, m, k, t;
    readf("%s %s %s %s", &n, &m, &k, &t);
    readln;

    auto arr = readln.chomp.split.map!(to!int).array;

    auto ds = new int[] (k);
    alias trap = Tuple!(int, bool);
    auto open = new int[][] (n+1);
    auto close = new int[][] (n+1);

    foreach (i; 0 .. k) {
        int le, r, d;
        readf("%s %s %s", &le, &r, &d);
        readln;

        ds[i] = d;
        open[le] ~= i;
        close[r] ~= i;
    }

    arr.sort();
    arr.reverse();

    bool isOk(int toBring) {

        int tot = 0;
        int threshold = arr[toBring-1];

        debug { writeln(toBring, ' ', threshold); }

        bool alone = false;
        int soldiersPos = 0;
        auto onPath = new bool[] (k);
        onPath[] = false;
        int onPathCnt = 0;
        foreach (i; 1 .. n+1) {
            foreach (idx; open[i]) {
                if (ds[idx] <= threshold) { continue; }

                onPath[idx] = true;
                onPathCnt += 1;
                alone = true;
            }

            foreach (idx; close[i]) {
                if (onPath[idx]) {
                    onPath[idx] = false;
                    onPathCnt -= 1;
                }
            }

            if (onPathCnt == 0) {
                if (alone) { tot += 2 * (i - soldiersPos); }
                tot += i - soldiersPos;
                soldiersPos = i;
                alone = false;
            }

            debug { writeln(i, ' ', soldiersPos, ' ', onPath, ' ', tot); }
        }

        tot += 1;
        return tot <= t;
    }

    int le = 0, r = n;
    while (le < r) {
        int c = (le + r) / 2 + 1;

        if (isOk(c)) { le = c; }
        else { r = c-1; }
    }

    le.writeln;
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n, m, k, t;
    readf("%s %s %s %s", &m, &n, &k, &t);
    readln;

    auto arr = readln.chomp.split.map!(to!int).array;

    auto ds = new int[] (n);
    alias trap = Tuple!(int, bool);
    auto open = new int[][] (n+1);
    auto close = new int[][] (n+1);

    foreach (i; 0 .. k) {
        int le, r, d;
        readf("%s %s %s", &le, &r, &d);
        readln;

        ds[i] = d;
        open[le] ~= i;
        close[r] ~= i;
    }

    arr.sort();
    arr.reverse();

    bool isOk(int toBring) {

        int tot = 0;
        int threshold = arr[toBring-1];

        debug { writeln(toBring, ' ', threshold); }

        bool alone = false;
        int soldiersPos = 0;
        auto onPath = new bool[] (k+1);
        onPath[] = false;
        int onPathCnt = 0;
        foreach (i; 1 .. n+1) {
            foreach (idx; open[i]) {
                if (ds[idx] <= threshold) { continue; }

                onPath[idx] = true;
                onPathCnt += 1;
                alone = true;
            }

            foreach (idx; close[i]) {
                if (onPath[idx]) {
                    onPath[idx] = false;
                    onPathCnt -= 1;
                }
            }

            if (onPathCnt == 0) {
                if (alone) { tot += 2 * (i - soldiersPos); }
                tot += i - soldiersPos;
                soldiersPos = i;
                alone = false;
            }

            debug { writeln(i, ' ', soldiersPos, ' ', onPath, ' ', tot); }
        }

        tot += 1;
        return tot <= t;
    }

    int le = 0, r = n;
    while (le < r) {
        int c = (le + r) / 2 + 1;

        if (isOk(c)) { le = c; }
        else { r = c-1; }
    }

    le.writeln;
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n, m, k, t;
    readf("%s %s %s %s", &n, &m, &k, &t);
    readln;

    auto arr = readln.chomp.split.map!(to!int).array;

    auto ds = new int[] (n);
    alias trap = Tuple!(int, bool);
    auto open = new int[][] (n+1);
    auto close = new int[][] (n+1);

    foreach (i; 0 .. k) {
        int le, r, d;
        readf("%s %s %s", &le, &r, &d);
        readln;

        ds[i] = d;
        open[le] ~= i;
        close[r] ~= i;
    }

    arr.sort();
    arr.reverse();

    bool isOk(int toBring) {

        int tot = 0;
        int threshold = arr[toBring-1];

        debug { writeln(toBring, ' ', threshold); }

        bool alone = false;
        int soldiersPos = 0;
        auto onPath = new bool[] (k+1);
        onPath[] = false;
        int onPathCnt = 0;
        foreach (i; 1 .. n+1) {
            foreach (idx; open[i]) {
                if (ds[idx] <= threshold) { continue; }

                onPath[idx] = true;
                onPathCnt += 1;
                alone = true;
            }

            foreach (idx; close[i]) {
                if (onPath[idx]) {
                    onPath[idx] = false;
                    onPathCnt -= 1;
                }
            }

            if (onPathCnt == 0) {
                if (alone) { tot += 2 * (i - soldiersPos); }
                tot += i - soldiersPos;
                soldiersPos = i;
                alone = false;
            }

            debug { writeln(i, ' ', soldiersPos, ' ', onPath, ' ', tot); }
        }

        tot += 1;
        return tot <= t;
    }

    int le = 0, r = n;
    while (le < r) {
        int c = (le + r) / 2 + 1;

        if (isOk(c)) { le = c; }
        else { r = c-1; }
    }

    le.writeln;
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n, m, k, t;
    readf("%s %s %s %s", &n, &m, &k, &t);
    readln;

    auto arr = readln.chomp.split.map!(to!int).array;

    auto ds = new int[] (n);
    alias trap = Tuple!(int, bool);
    auto open = new int[][] (n+1);
    auto close = new int[][] (n+1);

    foreach (i; 0 .. k) {
        int le, r, d;
        readf("%s %s %s", &le, &r, &d);
        readln;

        ds[i] = d;
        open[le] ~= i;
        close[r] ~= i;
    }

    arr.sort();
    arr.reverse();

    bool isOk(int toBring) {

        int tot = 0;
        int threshold = arr[toBring-1];

        debug { writeln(toBring, ' ', threshold); }

        bool alone = false;
        int soldiersPos = 0;
        auto onPath = new bool[] (n+1);
        onPath[] = false;
        int onPathCnt = 0;
        foreach (i; 1 .. n+1) {
            foreach (idx; open[i]) {
                if (ds[idx] <= threshold) { continue; }

                onPath[idx] = true;
                onPathCnt += 1;
                alone = true;
            }

            foreach (idx; close[i]) {
                if (onPath[idx]) {
                    onPath[idx] = false;
                    onPathCnt -= 1;
                }
            }

            if (onPathCnt == 0) {
                if (alone) { tot += 2 * (i - soldiersPos); }
                tot += i - soldiersPos;
                soldiersPos = i;
                alone = false;
            }

            debug { writeln(i, ' ', soldiersPos, ' ', onPath, ' ', tot); }
        }

        tot += 1;
        return tot <= t;
    }

    int le = 0, r = n;
    while (le < r) {
        int c = (le + r) / 2 + 1;

        if (isOk(c)) { le = c; }
        else { r = c-1; }
    }

    le.writeln;
}

import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string rstring(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T rtype(T)(){ return rstring.to!T; } alias rint = rtype!int, rlong = rtype!long, rreal = rtype!real;
T[] rtypes(T)(int n){ return n.iota.map!(i => rtype!T()).array; } alias rint = rtypes!int, rlong = rtypes!long, rreal = rtypes!real;
T[][] rtypess(T)(int n, int m){ return n.iota.map!(i => rtypes!T(m)).array; } alias rint = rtypess!int, rlong = rtypess!long, rreal = rtypess!real;
T chmin(T)(ref T x, T y){ if(x > y) x = y; return x; } T chmax(T)(ref T x, T y){ if(x < y) x = y; return x; }

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int m = rint, n = rint, k = rint, t = rint;
	long[] as = rlong(m);
	as.sort!"a>b"();

	X[] traps;
	foreach(i; 0 .. k) traps ~= X(rint, rint, rlong);

	bool isOK(int x){
		long a = (x > 0? as[x - 1]: 200_999);
		int rightend = 0;
		foreach(tr; traps) if(tr.d > a) rightend.chmax(tr.r);
		int time = rightend * 2 + n;
		return (time <= t);
	}

	int ans = uplimit(0, m, &isOK);
	ans.writeln;
}
struct X{
	int l, r;
	long d;
}
// 二分探索テンプレート
T uplimit(T)(T a, T c, bool delegate(T) f){
	if(f(c)) return c; if(! f(a)) return a - 1;
	while(a + 1 < c){ T b = (a + c) / 2; if(f(b)) a = b; else c = b; }
	return a;
}
T downlimit(T)(T a, T c, bool delegate(T) f){
	if(f(a)) return a; if(! f(c)) return c + 1;
	while(a + 1 < c){ T b = (a + c) / 2; if(f(b)) c = b; else a = b; }
	return c;
}

import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string rstring(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T rtype(T)(){ return rstring.to!T; } alias rint = rtype!int, rlong = rtype!long, rreal = rtype!real;
T[] rtypes(T)(int n){ return n.iota.map!(i => rtype!T()).array; } alias rint = rtypes!int, rlong = rtypes!long, rreal = rtypes!real;
T[][] rtypess(T)(int n, int m){ return n.iota.map!(i => rtypes!T(m)).array; } alias rint = rtypess!int, rlong = rtypess!long, rreal = rtypess!real;
T chmin(T)(ref T x, T y){ if(x > y) x = y; return x; } T chmax(T)(ref T x, T y){ if(x < y) x = y; return x; }

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int m = rint, n = rint, k = rint, t = rint;
	long[] as = rlong(m);
	as.sort!"a>b"();

	X[] traps;
	foreach(i; 0 .. k) traps ~= X(rint, rint, rlong);

	bool isOK(int x){
		long a = (x > 0? as[x - 1]: 200_999);
		int leftend = n + 1, rightend = 0;
		foreach(tr; traps) if(tr.d > a){
			leftend.chmin(tr.l);
			rightend.chmax(tr.r);
		}
		if(leftend > rightend) leftend = rightend;
		int time = (rightend - leftend) * 2 + (n + 1);
		log("x:", x, "leftend:", leftend, "rightend:", rightend, "time:", time);
		return (time <= t);
	}

	int ans = uplimit(0, m, &isOK);
	ans.writeln;
}
struct X{
	int l, r;
	long d;
}
// 二分探索テンプレート
T uplimit(T)(T a, T c, bool delegate(T) f){
	if(f(c)) return c; if(! f(a)) return a - 1;
	while(a + 1 < c){ T b = (a + c) / 2; if(f(b)) a = b; else c = b; }
	return a;
}
T downlimit(T)(T a, T c, bool delegate(T) f){
	if(f(a)) return a; if(! f(c)) return c + 1;
	while(a + 1 < c){ T b = (a + c) / 2; if(f(b)) c = b; else a = b; }
	return c;
}

import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string rstring(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T rtype(T)(){ return rstring.to!T; } alias rint = rtype!int, rlong = rtype!long, rreal = rtype!real;
T[] rtypes(T)(int n){ return n.iota.map!(i => rtype!T()).array; } alias rint = rtypes!int, rlong = rtypes!long, rreal = rtypes!real;
T[][] rtypess(T)(int n, int m){ return n.iota.map!(i => rtypes!T(m)).array; } alias rint = rtypess!int, rlong = rtypess!long, rreal = rtypess!real;
T chmin(T)(ref T x, T y){ if(x > y) x = y; return x; } T chmax(T)(ref T x, T y){ if(x < y) x = y; return x; }

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int m = rint, n = rint, k = rint, t = rint;
	long[] as = rlong(m);

	X[] traps;
	foreach(i; 0 .. k) traps ~= X(rint, rint, rlong);

	int rightmost = (t - (n + 1)) / 2;

	long dmax = 0;
	foreach(tr; traps) if(tr.r > rightmost) dmax.chmax(tr.d);

	int ans = 0;
	foreach(a; as) if(a >= dmax) ans += 1;
	ans.writeln;
}
struct X{
	int l, r;
	long d;
}

import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string rstring(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T rtype(T)(){ return rstring.to!T; } alias rint = rtype!int, rlong = rtype!long, rreal = rtype!real;
T[] rtypes(T)(int n){ return n.iota.map!(i => rtype!T()).array; } alias rint = rtypes!int, rlong = rtypes!long, rreal = rtypes!real;
T[][] rtypess(T)(int n, int m){ return n.iota.map!(i => rtypes!T(m)).array; } alias rint = rtypess!int, rlong = rtypess!long, rreal = rtypess!real;
T chmin(T)(ref T x, T y){ if(x > y) x = y; return x; } T chmax(T)(ref T x, T y){ if(x < y) x = y; return x; }

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int m = rint, n = rint, k = rint, t = rint;
	long[] as = rlong(m);
	as.sort!"a>b"();

	X[] traps;
	foreach(i; 0 .. k) traps ~= X(rint, rint, rlong);

	bool isOK(int x){
		long a = (x > 0? as[x - 1]: 200_999);
		int[] ls, rs;
		foreach(tr; traps) if(tr.d > a) ls ~= tr.l, rs ~= tr.r;
		ls.sort(), rs.sort();
		auto lq = new Queue!int(ls), rq = new Queue!int(rs);
		int leftpos = 0;
		int time = (n + 1);
		int cnt = 0;
		log("x:", x, "a:", a, "ls:", ls, "rs:", rs, "lq:", lq, "rq:", rq, "leftpos:", leftpos, "cnt:", cnt, "time:", time);
		while(lq.length + rq.length > 0){
			if(lq.length > 0 && lq.peek <= rq.peek){
				if(cnt == 0) leftpos = lq.peek;
				lq.deq, cnt += 1;
			}
			else{
				if(cnt == 1) time += (rq.peek - leftpos) * 2;
				rq.deq, cnt -= 1;
			}
			log("lq:", lq, "rq:", rq, "leftpos:", leftpos, "cnt:", cnt, "time:", time);
		}
//		log("x:", x, "a:", a, "leftend:", leftend, "rightend:", rightend, "time:", time, "isOK:", time <= t);
		return time <= t;

	}

	int ans = uplimit(0, m, &isOK);
	ans.writeln;
}
struct X{
	int l, r;
	long d;
}
// 二分探索テンプレート
T uplimit(T)(T a, T c, bool delegate(T) f){
	if(f(c)) return c; if(! f(a)) return a - 1;
	while(a + 1 < c){ T b = (a + c) / 2; if(f(b)) a = b; else c = b; }
	return a;
}
T downlimit(T)(T a, T c, bool delegate(T) f){
	if(f(a)) return a; if(! f(c)) return c + 1;
	while(a + 1 < c){ T b = (a + c) / 2; if(f(b)) c = b; else a = b; }
	return c;
}
// ----- キュー -----
class Queue(T){
	private T[] xs;
	private uint i, j; // i : 次に読み出す位置　j: 次に書き込む位置
	this(){	}
	this(T[] xs){ this.xs = xs; j = xs.length; }
	void enq(T x){
		while(j + 1 >= xs.length) xs.length = xs.length * 2 + 1;
		xs[j ++] = x;
	}
	ulong length(){ return j - i; }
	bool isEmpty(){ return j == i; }
	T deq(){ assert(i < j); return xs[i ++]; }
	T peek(){ assert(i < j); return xs[i]; }
	T[] array(){ return xs[i .. j]; }
	override string toString(){ return array.to!string; }
}
/*
5 6 4 14
1 2 3 4 5
1 5 2
1 2 5
3 4 5
3 5 3
*/


void main() {
  import std.stdio, std.string, std.conv, std.algorithm;
  import std.exception;

  int n;
  rd(n);
  auto a = readln.split.to!(int[]);
  sort(a);

  if (n == 1) {
    writeln("YES");
    writeln(a[0]);
    return;
  }

  auto freq = new int[](1234);
  foreach (el; a) {
    freq[el]++;
  }
  if (n % 2 == 0) {
    auto mat = new int[][](n, n);
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = el;
            freq[el] -= 4;
            break;
          }
        }
      }
    }
    if (freq.any!((el) => (el > 0))) {
      writeln("NO");
    } else {
      writeln("YES");
      writefln("%(%(%s %)\n%)", mat);
    }
  } else {
    auto mat = new int[][](n, n);
    foreach (el; a) {
      if (freq[el] % 4 == 1 || freq[el] % 4 == 3) {
        mat[n / 2][n / 2] = el;
        freq[el]--;
        break;
      }
    }
    if (freq.any!((el) => (el & 1))) {
      writeln("NO");
      return;
    }
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        foreach (el; a) {
          if (freq[el] > 2) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = el;
            freq[el] -= 4;
            break;
          }
        }
      }
    }
    foreach (i; 0 .. n / 2) {
      if (mat[i][n / 2] == 0) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 2 == 0) {
            mat[i][n / 2] = mat[n - i - 1][n / 2] = el;
            freq[el] -= 2;
            break;
          }
        }
      }
    }
    foreach (j; 0 .. n / 2) {
      if (mat[n / 2][j] == 0) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 2 == 0) {
            mat[n / 2][j] = mat[n / 2][n - j - 1] = el;
            freq[el] -= 2;
            break;
          }
        }
      }
    }
    if (freq.any!((el) => (el > 0))) {
      writeln("NO");
    } else {
      writeln("YES");
      writefln("%(%(%s %)\n%)", mat);
    }
  }
}

/*

7
5 9 5 4 1 9 8 4 5 1 4 10 7 7 8 4 2 4 4 5 4 4 10 3 4 6 8 1 9 9 5 6 8 7 1 8 6 6 7 5 3 1 1 4 7 2 3 3 8

*/

void rd(T...)(ref T x) {
  import std.stdio : readln;
  import std.string : split;
  import std.conv : to;

  auto l = readln.split;
  assert(l.length == x.length);
  foreach (i, ref e; x)
    e = l[i].to!(typeof(e));
}

void main() {
  import std.stdio, std.string, std.conv, std.algorithm;
  import std.exception;

  int n;
  rd(n);
  auto a = readln.split.to!(int[]);
  sort(a);

  if (n == 1) {
    writeln("YES");
    writeln(a[0]);
    return;
  }

  auto freq = new int[](1234);
  foreach (el; a) {
    freq[el]++;
  }
  if (n % 2 == 0) {
    auto mat = new int[][](n, n);
    int k = 0;
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        if (k < n * n) {
          if (freq[a[k]] > 0 && freq[a[k]] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = a[k];
            freq[a[k]] -= 4;
            k += 4;
          }
        }
      }
    }
    if (k != n * n) {
      writeln("NO");
    } else {
      writeln("YES");
      writefln("%(%(%s %)\n%)", mat);
    }
  } else {
    auto mat = new int[][](n, n);
    int od = 0;
    foreach(el; freq) {
      if (el & 1) {
        od++;
      }
    }
    if (od != 1) {
      writeln("NO");
      return;
    }
    foreach (el; a) {
      if (freq[el] % 4 == 1 || freq[el] % 4 == 3) {
        mat[n / 2][n / 2] = el;
        freq[el]--;
        break;
      }
    }
    foreach (i; 0 .. n / 2) {
      foreach (el; a) {
        if (freq[el] % 4 == 2) {
          mat[i][n / 2] = mat[n - i - 1][n / 2] = el;
          freq[el] -= 2;
          break;
        }
      }
    }
    foreach (j; 0 .. n / 2) {
      foreach (el; a) {
        if (freq[el] % 4 == 2) {
          mat[n / 2][j] = mat[n / 2][n - j - 1] = el;
          freq[el] -= 2;
          break;
        }
      }
    }
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = el;
            freq[el] -= 4;
            break;
          }
        }
      }
    }
    foreach (i; 0 .. n / 2) {
      if (mat[i][n / 2] == 0) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 2 == 0) {
            mat[i][n / 2] = mat[n - i - 1][n / 2] = el;
            freq[el] -= 2;
            break;
          }
        }
      }
    }
    foreach (j; 0 .. n / 2) {
      if (mat[n / 2][j] == 0) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 2 == 0) {
            mat[n / 2][j] = mat[n / 2][n - j - 1] = el;
            freq[el] -= 2;
            break;
          }
        }
      }
    }
    if (freq.any!((el) => (el != 0))) {
      writeln("NO");
    } else {
      writeln("YES");
      foreach (i; 0 .. n) {
        foreach (j; 0 .. n) {
          enforce(mat[i][j] > 0);
          enforce(mat[i][j] == mat[n - i - 1][j]);
          enforce(mat[i][j] == mat[i][n - j - 1]);
          enforce(mat[i][j] == mat[n - i - 1][n - j - 1]);
        }
      }
      writefln("%(%(%s %)\n%)", mat);
    }
  }
}

/*

7
1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3

*/

void rd(T...)(ref T x) {
  import std.stdio : readln;
  import std.string : split;
  import std.conv : to;

  auto l = readln.split;
  assert(l.length == x.length);
  foreach (i, ref e; x)
    e = l[i].to!(typeof(e));
}

void main() {
  import std.stdio, std.string, std.conv, std.algorithm;
  import std.exception;

  int n;
  rd(n);
  auto a = readln.split.to!(int[]);
  sort(a);

  if (n == 1) {
    writeln("YES");
    writeln(a[0]);
    return;
  }

  auto freq = new int[](1234);
  foreach (el; a) {
    freq[el]++;
  }
  if (n % 2 == 0) {
    auto mat = new int[][](n, n);
    int k = 0;
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        if (k < n * n) {
          if (freq[a[k]] > 0 && freq[a[k]] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = a[k];
            freq[a[k]] -= 4;
            k += 4;
          }
        }
      }
    }
    if (k != n * n) {
      writeln("NO");
    } else {
      writeln("YES");
      writefln("%(%(%s %)\n%)", mat);
    }
  } else {
    auto mat = new int[][](n, n);
    foreach (el; a) {
      if (freq[el] % 4 == 1 || freq[el] % 4 == 3) {
        mat[n / 2][n / 2] = el;
        freq[el]--;
        break;
      }
    }
    foreach (i; 0 .. n / 2) {
      foreach (el; a) {
        if (freq[el] % 4 == 2) {
          mat[i][n / 2] = mat[n - i - 1][n / 2] = el;
          freq[el] -= 2;
          break;
        }
      }
    }
    foreach (j; 0 .. n / 2) {
      foreach (el; a) {
        if (freq[el] % 4 == 2) {
          mat[n / 2][j] = mat[n / 2][n - j - 1] = el;
          freq[el] -= 2;
          break;
        }
      }
    }
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = el;
            freq[el] -= 4;
            break;
          }
        }
      }
    }
    foreach (i; 0 .. n / 2) {
      if (mat[i][n / 2] == 0) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 2 == 0) {
            mat[i][n / 2] = mat[n - i - 1][n / 2] = el;
            freq[el] -= 2;
            break;
          }
        }
      }
    }
    foreach (j; 0 .. n / 2) {
      if (mat[n / 2][j] == 0) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 2 == 0) {
            mat[n / 2][j] = mat[n / 2][n - j - 1] = el;
            freq[el] -= 2;
            break;
          }
        }
      }
    }
    if (freq.any!((el) => (el != 0))) {
      writeln("NO");
    } else {
      writeln("YES");
      foreach (i; 0 .. n) {
        foreach (j; 0 .. n) {
          enforce(mat[i][j] > 0);
          enforce(mat[i][j] == mat[n - i - 1][j]);
          enforce(mat[i][j] == mat[i][n - j - 1]);
          enforce(mat[i][j] == mat[n - i - 1][n - j - 1]);
        }
      }
      writefln("%(%(%s %)\n%)", mat);
    }
  }
}

/*

7
1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3

*/

void rd(T...)(ref T x) {
  import std.stdio : readln;
  import std.string : split;
  import std.conv : to;

  auto l = readln.split;
  assert(l.length == x.length);
  foreach (i, ref e; x)
    e = l[i].to!(typeof(e));
}

void main() {
  import std.stdio, std.string, std.conv, std.algorithm;

  int n;
  rd(n);
  auto a = readln.split.to!(int[]);
  sort(a);

  if (n == 1) {
    writeln("YES");
    writeln(a[0]);
    return;
  }

  auto freq = new int[](1234);
  foreach (el; a) {
    freq[el]++;
  }
  if (n % 2 == 0) {
    auto mat = new int[][](n, n);
    int k = 0;
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        if (k < n * n) {
          if (freq[a[k]] > 0 && freq[a[k]] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = a[k];
            freq[a[k]] -= 4;
            k += 4;
          }
        }
      }
    }
    if (k != n * n) {
      writeln("NO");
    } else {
      writeln("YES");
      writefln("%(%(%s %)\n%)", mat);
    }
  } else {
    auto mat = new int[][](n, n);
    foreach (el; a) {
      if (freq[el] % 4 == 1 || freq[el] % 4 == 3) {
        mat[n / 2][n / 2] = el;
        freq[el]--;
        break;
      }
    }
    foreach (i; 0 .. n / 2) {
      foreach (el; a) {
        if (freq[el] % 4 == 2) {
          mat[i][n / 2] = mat[n - i - 1][n / 2] = el;
          freq[el] -= 2;
          break;
        }
      }
    }
    foreach (j; 0 .. n / 2) {
      foreach (el; a) {
        if (freq[el] % 4 == 2) {
          mat[n / 2][j] = mat[n / 2][n - j - 1] = el;
          freq[el] -= 2;
          break;
        }
      }
    }
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = el;
            freq[el] -= 4;
            break;
          }
        }
      }
    }
    foreach (i; 0 .. n / 2) {
      foreach (el; a) {
        if (freq[el] > 0 && freq[el] % 2 == 0) {
          mat[i][n / 2] = mat[n - i - 1][n / 2] = el;
          freq[el] -= 2;
          break;
        }
      }
    }
    foreach (j; 0 .. n / 2) {
      foreach (el; a) {
        if (freq[el] > 0 && freq[el] % 2 == 0) {
          mat[n / 2][j] = mat[n / 2][n - j - 1] = el;
          freq[el] -= 2;
          break;
        }
      }
    }
    if (freq.any!((el) => (el != 0))) {
      writeln("NO");
    } else {
      writeln("YES");
      writefln("%(%(%s %)\n%)", mat);
    }
  }
}

/*

*/

void rd(T...)(ref T x) {
  import std.stdio : readln;
  import std.string : split;
  import std.conv : to;

  auto l = readln.split;
  assert(l.length == x.length);
  foreach (i, ref e; x)
    e = l[i].to!(typeof(e));
}

void main() {
  import std.stdio, std.string, std.conv, std.algorithm;
  import std.exception;

  int n;
  rd(n);
  auto a = readln.split.to!(int[]);
  sort(a);

  if (n == 1) {
    writeln("YES");
    writeln(a[0]);
    return;
  }

  auto freq = new int[](1234);
  foreach (el; a) {
    freq[el]++;
  }
  if (n % 2 == 0) {
    auto mat = new int[][](n, n);
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = el;
            freq[el] -= 4;
            break;
          }
        }
      }
    }
    if (freq.any!((el) => (el > 0))) {
      writeln("NO");
    } else {
      writeln("YES");
      writefln("%(%(%s %)\n%)", mat);
    }
  } else {
    auto mat = new int[][](n, n);
    foreach (el; a) {
      if (freq[el] % 4 == 1 || freq[el] % 4 == 3) {
        mat[n / 2][n / 2] = el;
        freq[el]--;
        break;
      }
    }
    foreach (i; 0 .. n / 2) {
      foreach (j; 0 .. n / 2) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 4 == 0) {
            mat[i][j] = mat[n - i - 1][j] = mat[i][n - j - 1] = mat[n - i - 1][n - j - 1] = el;
            freq[el] -= 4;
            break;
          }
        }
      }
    }
    foreach (i; 0 .. n / 2) {
      if (mat[i][n / 2] == 0) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 2 == 0) {
            mat[i][n / 2] = mat[n - i - 1][n / 2] = el;
            freq[el] -= 2;
            break;
          }
        }
      }
    }
    foreach (j; 0 .. n / 2) {
      if (mat[n / 2][j] == 0) {
        foreach (el; a) {
          if (freq[el] > 0 && freq[el] % 2 == 0) {
            mat[n / 2][j] = mat[n / 2][n - j - 1] = el;
            freq[el] -= 2;
            break;
          }
        }
      }
    }
    if (freq.any!((el) => (el != 0))) {
      writeln("NO");
    } else {
      writeln("YES");
      writefln("%(%(%s %)\n%)", mat);
    }
  }
}

/*

7
1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3

*/

void rd(T...)(ref T x) {
  import std.stdio : readln;
  import std.string : split;
  import std.conv : to;

  auto l = readln.split;
  assert(l.length == x.length);
  foreach (i, ref e; x)
    e = l[i].to!(typeof(e));
}


//prewritten code: https://github.com/antma/algo
module Solution;
import std.algorithm;
import std.array;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.traits;
import std.bitmanip;
import core.bitop;
import std.exception;

final class InputReader {
  private:
  ubyte[] p, buffer;
  bool eof;
  bool rawRead () {
    if (eof) {
      return false;
    }
    p = stdin.rawRead (buffer);
    if (p.empty) {
      eof = true;
      return false;
    }
    return true;
  }
  ubyte nextByte(bool check) () {
    static if (check) {
      if (p.empty) {
        if (!rawRead ()) {
          return 0;
        }
      }
    }
    auto r = p.front;
    p.popFront ();
    return r;
  }
  public:
  this () {
    buffer = uninitializedArray!(ubyte[])(16<<20);
  }
  bool seekByte (in ubyte lo) {
    while (true) {
      p = p.find! (c => c >= lo);
      if (!p.empty) {
        return false;
      }
      if (!rawRead ()) {
        return true;
      }
    }
  }
  template next(T) if (isSigned!T) {
    T next ()  {
      if (seekByte (45)) {
        return 0;
      }
      T res;
      ubyte b = nextByte!false ();
      if (b == 45) {
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 - (b - 48);
        }
      } else {
        res = b - 48;
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 + (b - 48);
        }
      }
    }
  }
  template next(T) if (isUnsigned!T) {
    T next () {
      if (seekByte (48)) {
        return 0;
      }
      T res = nextByte!false () - 48;
      while (true) {
        ubyte b = nextByte!true ();
        if (b < 48 || b >= 58) {
          break;
        }
        res = res * 10 + (b - 48);
      }
      return res;
    }
  }
  T[] nextA(T) (in int n) {
    auto a = uninitializedArray!(T[]) (n);
    foreach (i; 0 .. n) {
      a[i] = next!T;
    }
    return a;
  }
}

alias MoResult = int;

struct MoQuery {
  int u, v;//inclusive
  MoResult res;
}

abstract class MoState {
  public:
  @property
  abstract bool fastReset () const;
  abstract void reset ();
  //[l, r)
  abstract void add (int l, int r);
  abstract void del (int l, int r);
  abstract MoResult result () const;
}

struct MoRange {
  int l, r;
  bool fastReset;
  static immutable d = [3, 0, 0, 1];
  static long hilbert (const int x, const int y, const int k, const int a) {
    if (k < 0) return 0L;
    immutable int m = ~(1 << k), o = 3 & (((x >> k) ^ 3 * (y >> k)) + a);
    immutable long b = hilbert (x & m, y & m, k - 1, a + d[o]), ss = 1L << (2 * k);
    return ss * o + (o == 1 || o == 2 ? b : (ss - (b + 1)));
  }
  static size_t[] makeIdx (in MoQuery[] queries, const int t) {
    immutable nq = queries.length;
    auto x = uninitializedArray!(long[])(nq);
    foreach (i, const ref q; queries) {
      x[i] = hilbert (q.u, q.v, t, 0);
    }
    auto idx = uninitializedArray!(size_t[])(nq);
    makeIndex (x, idx);
    return idx;
  }
  void move (MoState s, ref MoQuery q) {
    if (l > r || (fastReset && (l > q.v || r < q.u))) {
      l = q.u;
      r = l - 1;
      s.reset ();
    }
    if (r < q.v) {
      s.add (r + 1, q.v + 1);
      r = q.v;
    } else if (r > q.v) {
      s.del (q.v + 1, r + 1);
      r = q.v;
    }
    if (l > q.u) {
      s.add (q.u, l);
      l = q.u;
    } else if (l < q.u) {
      s.del (l, q.u);
      l = q.u;
    }
    q.res = s.result ();
  }
  void processQueries (MoState s, MoQuery[] queries) {
    l = 0; r = -1; fastReset = s.fastReset;
    auto idx = makeIdx (queries, bsr (reduce!max(0, queries.map!(t => t.v)) + 1));
    foreach (j; idx) {
      move (s, queries[j]);
    }
  }
}

final class EState : MoState {
  private:
  uint[] x;
  int[] ba;
  int sz;
  public:
  @property
  override bool fastReset () const {
    return false;
  }
  override void reset () {
    ba[] = 0;
    sz = 0;
  }
  //[l, r)
  override void add (int l, int r) {
    foreach (k; x[l .. r]) {
      if (++ba[k] == 1) ++sz;
    }
  }
  override void del (int l, int r) {
    foreach (k; x[l .. r]) {
      if (!--ba[k]) --sz;
    }
  }
  override MoResult result () const {
    return sz;
  }
  this (uint[] x, int n) {
    this.x = x;
    ba = new int[n];
  }
}

void test (in int n, uint[] a) {
  debug stderr.writeln ("a = ", a);
  auto v = new int[n];
  foreach (i; 0 .. n) {
    v[i] = i;
  }
  auto prev = uninitializedArray!(int[]) (n);

  MoQuery[] q;

  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      q ~= MoQuery (prev[j] + 1, i.to!int - 1);
    }
    prev[j] = pos;
  }
  foreach (i; 0 .. n) {
    q ~= MoQuery (prev[i] + 1, a.length.to!int - 1);
  }

  auto state = new EState (a, n);
  MoRange rng;
  rng.processQueries (state, q);
  state = null;

  int cur;
  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      auto k = q[cur++].res;
      v[j] = max (v[j], k);
    }
    prev[j] = pos;
  }

  foreach (i; 0 .. n) {
    auto k = q[cur++].res;
    v[i] = max (v[i], k);
  }

  q = null;

  foreach (i; 0 .. n) {
    int j = v[i];
    int u = i;
    if (prev[i] >= n) {
      u = 0;
    }
    writeln (u + 1, ' ', j + 1);
  }
}

void main() {
  auto r = new InputReader ();
  immutable n = r.next!uint;
  immutable m = r.next!uint;
  auto a = uninitializedArray!(uint[]) (n + m);
  foreach (i; 0 .. n) a[i] = n - 1 - i;
  foreach (i; 0 .. m) a[n+i] = r.next!uint - 1;
  a.length -= uniq (a).copy (a).length;
  test (n, a);
}

//prewritten code: https://github.com/antma/algo
module Solution;
import std.algorithm;
import std.array;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.traits;
import std.bitmanip;
import core.bitop;
import std.exception;

final class InputReader {
  private:
  ubyte[] p, buffer;
  bool eof;
  bool rawRead () {
    if (eof) {
      return false;
    }
    p = stdin.rawRead (buffer);
    if (p.empty) {
      eof = true;
      return false;
    }
    return true;
  }
  ubyte nextByte(bool check) () {
    static if (check) {
      if (p.empty) {
        if (!rawRead ()) {
          return 0;
        }
      }
    }
    auto r = p.front;
    p.popFront ();
    return r;
  }
  public:
  this () {
    buffer = uninitializedArray!(ubyte[])(16<<20);
  }
  bool seekByte (in ubyte lo) {
    while (true) {
      p = p.find! (c => c >= lo);
      if (!p.empty) {
        return false;
      }
      if (!rawRead ()) {
        return true;
      }
    }
  }
  template next(T) if (isSigned!T) {
    T next ()  {
      if (seekByte (45)) {
        return 0;
      }
      T res;
      ubyte b = nextByte!false ();
      if (b == 45) {
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 - (b - 48);
        }
      } else {
        res = b - 48;
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 + (b - 48);
        }
      }
    }
  }
  template next(T) if (isUnsigned!T) {
    T next () {
      if (seekByte (48)) {
        return 0;
      }
      T res = nextByte!false () - 48;
      while (true) {
        ubyte b = nextByte!true ();
        if (b < 48 || b >= 58) {
          break;
        }
        res = res * 10 + (b - 48);
      }
      return res;
    }
  }
  T[] nextA(T) (in int n) {
    auto a = uninitializedArray!(T[]) (n);
    foreach (i; 0 .. n) {
      a[i] = next!T;
    }
    return a;
  }
}

alias MoResult = int;

struct MoQuery {
  int u, v;//inclusive
  MoResult res;
}

abstract class MoState {
  public:
  @property
  abstract bool fastReset () const;
  abstract void reset ();
  //[l, r)
  abstract void add (int l, int r);
  abstract void del (int l, int r);
  abstract MoResult result () const;
}

struct MoRange {
  int l, r;
  bool fastReset;
  static immutable hilbertDirs = [3, 0, 0, 1];
  static long hilbert (int x, int y, int k, int a) {
    if (k < 0) return 0L;
    int m = 1 << k, o = 3 & (((x >> k) ^ 3 * (y >> k)) + a);
    long ss = 1L << (2 * k), b = hilbert (x & ~m, y & ~m, k - 1, a + hilbertDirs[o]);
    return ss * o + (o == 1 || o == 2 ? b : (ss - (b + 1)));
  }
  void move (MoState s, ref MoQuery q) {
    if (l > r || (fastReset && (l > q.v || r < q.u))) {
      l = q.u;
      r = l - 1;
      s.reset ();
    }
    if (r < q.v) {
      s.add (r + 1, q.v + 1);
      r = q.v;
    } else if (r > q.v) {
      s.del (q.v + 1, r + 1);
      r = q.v;
    }
    if (l > q.u) {
      s.add (q.u, l);
      l = q.u;
    } else if (l < q.u) {
      s.del (l, q.u);
      l = q.u;
    }
    q.res = s.result ();
  }
  void processQueries (MoState s, MoQuery[] queries) {
    l = 0;
    r = -1;
    fastReset = s.fastReset;
    auto nq = queries.length;
    auto n = reduce!max(queries.map!(t => t.v));
    debug stderr.writeln ("n = ", n);
    auto t = bsr (n + 1);
    auto x = queries.map!(q => hilbert (q.u, q.v, t, 0)).array;
    auto idx = uninitializedArray!(size_t[]) (nq);
    makeIndex (x, idx);
    x = null;
    foreach (j; idx) {
      move (s, queries[j]);
    }
  }
}

final class EState : MoState {
  private:
  uint[] x;
  int[] ba;
  int sz;
  public:
  @property
  override bool fastReset () const {
    return false;
  }
  override void reset () {
    ba[] = 0;
    sz = 0;
  }
  //[l, r)
  override void add (int l, int r) {
    foreach (k; x[l .. r]) {
      if (++ba[k] == 1) ++sz;
    }
  }
  override void del (int l, int r) {
    foreach (k; x[l .. r]) {
      if (!--ba[k]) --sz;
    }
  }
  override MoResult result () const {
    return sz;
  }
  this (uint[] x, int n) {
    this.x = x;
    ba = new int[n];
  }
}

void test (in int n, uint[] a) {
  debug stderr.writeln ("a = ", a);
  auto v = new int[n];
  foreach (i; 0 .. n) {
    v[i] = i;
  }
  auto prev = uninitializedArray!(int[]) (n);

  MoQuery[] q;

  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      q ~= MoQuery (prev[j] + 1, i.to!int - 1);
    }
    prev[j] = pos;
  }
  foreach (i; 0 .. n) {
    q ~= MoQuery (prev[i] + 1, a.length.to!int - 1);
  }

  auto state = new EState (a, n);
  MoRange rng;
  rng.processQueries (state, q);
  state = null;

  int cur;
  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      auto k = q[cur++].res;
      v[j] = max (v[j], k);
    }
    prev[j] = pos;
  }

  foreach (i; 0 .. n) {
    auto k = q[cur++].res;
    v[i] = max (v[i], k);
  }

  q = null;

  foreach (i; 0 .. n) {
    int j = v[i];
    int u = i;
    if (prev[i] >= n) {
      u = 0;
    }
    writeln (u + 1, ' ', j + 1);
  }
}

void main() {
  auto r = new InputReader ();
  immutable n = r.next!uint;
  immutable m = r.next!uint;
  auto a = uninitializedArray!(uint[]) (n + m);
  foreach (i; 0 .. n) a[i] = n - 1 - i;
  foreach (i; 0 .. m) a[n+i] = r.next!uint - 1;
  a.length -= uniq (a).copy (a).length;
  test (n, a);
}

//prewritten code: https://github.com/antma/algo
import std.algorithm;
import std.array;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.traits;
import std.bitmanip;
import core.bitop;

final class SegmentTree(T = int, alias op="a+b", T zero) {
  private:
  T [] t;
  size_t n;
  void build () {
    foreach_reverse (i; 1 .. n) {
      immutable k = i << 1;
      t[i] = binaryFun!op (t[k], t[k+1]);
    }
  }
  public:
  void update (size_t p, T v) {
    for (t[p += n] = v; p > 1; p >>= 1) {
      t[p>>1] = binaryFun!op (t[p], t[p ^ 1]);
    }
  }
  T reduce (size_t l, size_t r) {
    T res = zero;
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) {
        res = binaryFun!op (res, t[l++]);
      }
      if (r & 1) {
        res = binaryFun!op (t[--r], res);
      }
    }
    return res;
  }
  this (T[] a) {
    n = a.length;
    t = uninitializedArray!(T[])(n);
    t ~= a;
    build ();
  }
}

final class InputReader {
  private:
  ubyte[] p, buffer;
  bool eof;
  bool rawRead () {
    if (eof) {
      return false;
    }
    p = stdin.rawRead (buffer);
    if (p.empty) {
      eof = true;
      return false;
    }
    return true;
  }
  ubyte nextByte(bool check) () {
    static if (check) {
      if (p.empty) {
        if (!rawRead ()) {
          return 0;
        }
      }
    }
    auto r = p.front;
    p.popFront ();
    return r;
  }
  public:
  this () {
    buffer = uninitializedArray!(ubyte[])(16<<20);
  }
  bool seekByte (in ubyte lo) {
    while (true) {
      p = p.find! (c => c >= lo);
      if (!p.empty) {
        return false;
      }
      if (!rawRead ()) {
        return true;
      }
    }
  }
  template next(T) if (isSigned!T) {
    T next ()  {
      if (seekByte (45)) {
        return 0;
      }
      T res;
      ubyte b = nextByte!false ();
      if (b == 45) {
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 - (b - 48);
        }
      } else {
        res = b - 48;
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 + (b - 48);
        }
      }
    }
  }
  template next(T) if (isUnsigned!T) {
    T next () {
      if (seekByte (48)) {
        return 0;
      }
      T res = nextByte!false () - 48;
      while (true) {
        ubyte b = nextByte!true ();
        if (b < 48 || b >= 58) {
          break;
        }
        res = res * 10 + (b - 48);
      }
      return res;
    }
  }
  T[] nextA(T) (in int n) {
    auto a = uninitializedArray!(T[]) (n);
    foreach (i; 0 .. n) {
      a[i] = next!T;
    }
    return a;
  }
}

uint[] mrg (uint[] a, uint[] b) {
  return merge (a, b).uniq.array;
}

struct MoQuery {
  int u;
  int v;
}

alias R = int;
final class MoRange {
  private:
  immutable uint[] x;
  int l, r;
  //CUSTOM
  BitArray ba;
  int sz;

  static long hilbert (int x, int y, int k, int a) {
    static immutable d = [3, 0, 0, 1];
    if (k < 0) return 0L;
    int m = 1 << k, o = 3 & (((x >> k) ^ 3 * (y >> k)) + a);
    long ss = 1L << (2 * k), b = hilbert (x & ~m, y & ~m, k - 1, a + d[o]);
    return ss * o + (o == 1 || o == 2 ? b : (ss - (b + 1)));
  }

  void clear () {
    //CUSTOM
    ba[] = false;
    sz = 0;
  }

  R move (ref in MoQuery q) {
    if (l > r || l > q.v || r < q.u) {
      l = q.u;
      r = l - 1;
      clear ();
    }
    if (r < q.v) {
      add (r + 1, q.v + 1);
      r = q.v;
    } else if (r > q.v) {
      del (q.v + 1, r + 1);
      r = q.v;
    }
    if (l > q.u) {
      add (q.u, l);
      l = q.u;
    } else if (l < q.u) {
      del (l, q.u);
      l = q.u;
    }
    //CUSTOM
    return sz;
  }
  void add (const int a, const int b) {
    debug stderr.writefln ("add (%d, %d)", a, b);
    foreach (k; x[a .. b]) {
      if (!ba[k]) {
        ba[k] = true;
        ++sz;
      }
    }
  }
  void del (const int a, const int b) {
    foreach (k; x[a .. b]) {
      //assert (freq[k] > 0, format!"freq[%d] = %d" (k, freq[k]));
      if (ba[k]) {
        ba[k] = false;
        --sz;
      }
    }
  }
  int[] processQueries (in MoQuery[] queries) {
    l = 0;
    r = -1;
    auto nq = queries.length;
    auto n = reduce!max(queries.map!(t => t.v));
    auto s = bsr (n);
    auto x = queries.map!(q => hilbert (q.u, q.v, s, 0)).array;
    auto idx = uninitializedArray!(size_t[]) (nq);
    makeIndex (x, idx);
    auto res = uninitializedArray!(R[]) (nq);
    foreach (j; idx) {
      if (queries[j].u > queries[j].v) res[j] = 0;
      else res[j] = move (queries[j]);
    }
    return res;
  }
  this (in uint[] a, int n) {
    x = a.idup;
    //CUSTOM
    ba.length = n;
  }
}

alias ST = SegmentTree!(uint[], mrg, []);

void test (in int n, uint[] a) {
  debug stderr.writeln ("a = ", a);
  auto v = new int[n];
  foreach (i; 0 .. n) {
    v[i] = i;
  }
  auto prev = uninitializedArray!(int[]) (n);

  MoQuery[] q;

  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      q ~= MoQuery (prev[j] + 1, i.to!int - 1);
    }
    prev[j] = pos;
  }
  foreach (i; 0 .. n) {
    q ~= MoQuery (prev[i] + 1, a.length.to!int - 1);
  }

  auto solve = new MoRange (a, n);
  auto res = solve.processQueries (q);

  int cur;
  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      auto k = res[cur++];
      v[j] = max (v[j], k);
    }
    prev[j] = pos;
  }
  foreach (i; 0 .. n) {
    auto k = res[cur++];
    v[i] = max (v[i], k);
  }

  foreach (i; 0 .. n) {
    int j = v[i];
    int u = i;
    if (prev[i] >= n) {
      u = 0;
    }
    writeln (u + 1, ' ', j + 1);
  }
}

void main() {
  auto r = new InputReader ();
  immutable n = r.next!uint;
  immutable m = r.next!uint;
  auto a = r.nextA!uint (m);
  foreach (i; 0 .. m) --a[i];
  auto b = new uint[n];
  foreach (i; 0 .. n) b[i] = n - 1 - i;
  b ~= a;
  a = b;
  b = null;
  //a.length -= uniq (a).copy (a).length;
  test (n, a);
}

//prewritten code: https://github.com/antma/algo
import std.algorithm;
import std.array;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.traits;
import std.bitmanip;
import core.bitop;

final class SegmentTree(T = int, alias op="a+b", T zero) {
  private:
  T [] t;
  size_t n;
  void build () {
    foreach_reverse (i; 1 .. n) {
      immutable k = i << 1;
      t[i] = binaryFun!op (t[k], t[k+1]);
    }
  }
  public:
  void update (size_t p, T v) {
    for (t[p += n] = v; p > 1; p >>= 1) {
      t[p>>1] = binaryFun!op (t[p], t[p ^ 1]);
    }
  }
  T reduce (size_t l, size_t r) {
    T res = zero;
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) {
        res = binaryFun!op (res, t[l++]);
      }
      if (r & 1) {
        res = binaryFun!op (t[--r], res);
      }
    }
    return res;
  }
  this (T[] a) {
    n = a.length;
    t = uninitializedArray!(T[])(n);
    t ~= a;
    build ();
  }
}

final class InputReader {
  private:
  ubyte[] p, buffer;
  bool eof;
  bool rawRead () {
    if (eof) {
      return false;
    }
    p = stdin.rawRead (buffer);
    if (p.empty) {
      eof = true;
      return false;
    }
    return true;
  }
  ubyte nextByte(bool check) () {
    static if (check) {
      if (p.empty) {
        if (!rawRead ()) {
          return 0;
        }
      }
    }
    auto r = p.front;
    p.popFront ();
    return r;
  }
  public:
  this () {
    buffer = uninitializedArray!(ubyte[])(16<<20);
  }
  bool seekByte (in ubyte lo) {
    while (true) {
      p = p.find! (c => c >= lo);
      if (!p.empty) {
        return false;
      }
      if (!rawRead ()) {
        return true;
      }
    }
  }
  template next(T) if (isSigned!T) {
    T next ()  {
      if (seekByte (45)) {
        return 0;
      }
      T res;
      ubyte b = nextByte!false ();
      if (b == 45) {
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 - (b - 48);
        }
      } else {
        res = b - 48;
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 + (b - 48);
        }
      }
    }
  }
  template next(T) if (isUnsigned!T) {
    T next () {
      if (seekByte (48)) {
        return 0;
      }
      T res = nextByte!false () - 48;
      while (true) {
        ubyte b = nextByte!true ();
        if (b < 48 || b >= 58) {
          break;
        }
        res = res * 10 + (b - 48);
      }
      return res;
    }
  }
  T[] nextA(T) (in int n) {
    auto a = uninitializedArray!(T[]) (n);
    foreach (i; 0 .. n) {
      a[i] = next!T;
    }
    return a;
  }
}

uint[] mrg (uint[] a, uint[] b) {
  return merge (a, b).uniq.array;
}

struct MoQuery {
  int u;
  int v;
}

alias R = int;
final class MoRange {
  private:
  immutable uint[] x;
  int l, r;
  //CUSTOM
  BitArray ba;
  int sz;

  static long hilbert (int x, int y, int k, int a) {
    static immutable d = [3, 0, 0, 1];
    if (k < 0) return 0L;
    int m = 1 << k, o = 3 & (((x >> k) ^ 3 * (y >> k)) + a);
    long ss = 1L << (2 * k), b = hilbert (x & ~m, y & ~m, k - 1, a + d[o]);
    return ss * o + (o == 1 || o == 2 ? b : (ss - (b + 1)));
  }

  void clear () {
    //CUSTOM
    ba[] = false;
    sz = 0;
  }

  R move (ref in MoQuery q) {
    if (l > r || l > q.v || r < q.u) {
      l = q.u;
      r = l - 1;
      clear ();
    }
    if (r < q.v) {
      add (r + 1, q.v + 1);
      r = q.v;
    } else if (r > q.v) {
      del (q.v + 1, r + 1);
      r = q.v;
    }
    if (l > q.u) {
      add (q.u, l);
      l = q.u;
    } else if (l < q.u) {
      del (l, q.u);
      l = q.u;
    }
    //CUSTOM
    return sz;
  }
  void add (const int a, const int b) {
    debug stderr.writefln ("add (%d, %d)", a, b);
    foreach (k; x[a .. b]) {
      if (!ba[k]) {
        ba[k] = true;
        ++sz;
      }
    }
  }
  void del (const int a, const int b) {
    foreach (k; x[a .. b]) {
      //assert (freq[k] > 0, format!"freq[%d] = %d" (k, freq[k]));
      if (ba[k]) {
        ba[k] = false;
        --sz;
      }
    }
  }
  int[] processQueries (in MoQuery[] queries) {
    l = 0;
    r = -1;
    auto nq = queries.length;
    auto n = reduce!max(queries.map!(t => t.v));
    auto s = bsr (n);
    auto x = queries.map!(q => hilbert (q.u, q.v, s, 0)).array;
    auto idx = uninitializedArray!(size_t[]) (nq);
    makeIndex (x, idx);
    auto res = uninitializedArray!(R[]) (nq);
    foreach (j; idx) {
      if (queries[j].u > queries[j].v) res[j] = 0;
      else res[j] = move (queries[j]);
    }
    return res;
  }
  this (in uint[] a, int n) {
    x = a.idup;
    //CUSTOM
    ba.length = n;
  }
}

alias ST = SegmentTree!(uint[], mrg, []);

void test (in int n, uint[] a) {
  debug stderr.writeln ("a = ", a);
  auto v = new int[n];
  foreach (i; 0 .. n) {
    v[i] = i;
  }
  auto prev = uninitializedArray!(int[]) (n);

  MoQuery[] q;

  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      q ~= MoQuery (prev[j] + 1, i.to!int - 1);
    }
    prev[j] = pos;
  }
  foreach (i; 0 .. n) {
    q ~= MoQuery (prev[i] + 1, a.length.to!int - 1);
  }

  auto solve = new MoRange (a, n);
  auto res = solve.processQueries (q);

  int cur;
  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      auto k = res[cur++];
      v[j] = max (v[j], k);
    }
    prev[j] = pos;
  }
  foreach (i; 0 .. n) {
    auto k = res[cur++];
    v[i] = max (v[i], k);
  }

  foreach (i; 0 .. n) {
    int j = v[i];
    int u = i;
    if (prev[i] >= n) {
      u = 0;
    }
    writeln (u + 1, ' ', j + 1);
  }
}

void main() {
  auto r = new InputReader ();
  immutable n = r.next!uint;
  immutable m = r.next!uint;
  auto a = r.nextA!uint (m);
  foreach (i; 0 .. m) --a[i];
  auto b = new uint[n];
  foreach (i; 0 .. n) b[i] = n - 1 - i;
  b ~= a;
  a = b;
  b = null;
  a.length -= uniq (a).copy (a).length;
  test (n, a);
}

//prewritten code: https://github.com/antma/algo
import std.algorithm;
import std.array;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.traits;
import std.bitmanip;
import core.bitop;

final class SegmentTree(T = int, alias op="a+b", T zero) {
  private:
  T [] t;
  size_t n;
  void build () {
    foreach_reverse (i; 1 .. n) {
      immutable k = i << 1;
      t[i] = binaryFun!op (t[k], t[k+1]);
    }
  }
  public:
  void update (size_t p, T v) {
    for (t[p += n] = v; p > 1; p >>= 1) {
      t[p>>1] = binaryFun!op (t[p], t[p ^ 1]);
    }
  }
  T reduce (size_t l, size_t r) {
    T res = zero;
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) {
        res = binaryFun!op (res, t[l++]);
      }
      if (r & 1) {
        res = binaryFun!op (t[--r], res);
      }
    }
    return res;
  }
  this (T[] a) {
    n = a.length;
    t = uninitializedArray!(T[])(n);
    t ~= a;
    build ();
  }
}

final class InputReader {
  private:
  ubyte[] p, buffer;
  bool eof;
  bool rawRead () {
    if (eof) {
      return false;
    }
    p = stdin.rawRead (buffer);
    if (p.empty) {
      eof = true;
      return false;
    }
    return true;
  }
  ubyte nextByte(bool check) () {
    static if (check) {
      if (p.empty) {
        if (!rawRead ()) {
          return 0;
        }
      }
    }
    auto r = p.front;
    p.popFront ();
    return r;
  }
  public:
  this () {
    buffer = uninitializedArray!(ubyte[])(16<<20);
  }
  bool seekByte (in ubyte lo) {
    while (true) {
      p = p.find! (c => c >= lo);
      if (!p.empty) {
        return false;
      }
      if (!rawRead ()) {
        return true;
      }
    }
  }
  template next(T) if (isSigned!T) {
    T next ()  {
      if (seekByte (45)) {
        return 0;
      }
      T res;
      ubyte b = nextByte!false ();
      if (b == 45) {
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 - (b - 48);
        }
      } else {
        res = b - 48;
        while (true) {
          b = nextByte!true ();
          if (b < 48 || b >= 58) {
            return res;
          }
          res = res * 10 + (b - 48);
        }
      }
    }
  }
  template next(T) if (isUnsigned!T) {
    T next () {
      if (seekByte (48)) {
        return 0;
      }
      T res = nextByte!false () - 48;
      while (true) {
        ubyte b = nextByte!true ();
        if (b < 48 || b >= 58) {
          break;
        }
        res = res * 10 + (b - 48);
      }
      return res;
    }
  }
  T[] nextA(T) (in int n) {
    auto a = uninitializedArray!(T[]) (n);
    foreach (i; 0 .. n) {
      a[i] = next!T;
    }
    return a;
  }
}

uint[] mrg (uint[] a, uint[] b) {
  return merge (a, b).uniq.array;
}

struct MoQuery {
  int u;
  int v;
}

alias R = int;
final class MoRange {
  private:
  immutable uint[] x;
  int l, r;
  //CUSTOM
  BitArray ba;
  int sz;

  static long hilbert (int x, int y, int k, int a) {
    static immutable d = [3, 0, 0, 1];
    if (k < 0) return 0L;
    int m = 1 << k, o = 3 & (((x >> k) ^ 3 * (y >> k)) + a);
    long ss = 1L << (2 * k), b = hilbert (x & ~m, y & ~m, k - 1, a + d[o]);
    return ss * o + (o == 1 || o == 2 ? b : (ss - (b + 1)));
  }

  void clear () {
    //CUSTOM
    ba[] = false;
    sz = 0;
  }

  R move (ref in MoQuery q) {
    if (l > r || l > q.v || r < q.u) {
      l = q.u;
      r = l - 1;
      clear ();
    }
    if (r < q.v) {
      add (r + 1, q.v + 1);
      r = q.v;
    } else if (r > q.v) {
      del (q.v + 1, r + 1);
      r = q.v;
    }
    if (l > q.u) {
      add (q.u, l);
      l = q.u;
    } else if (l < q.u) {
      del (l, q.u);
      l = q.u;
    }
    //CUSTOM
    return sz;
  }
  void add (const int a, const int b) {
    debug stderr.writefln ("add (%d, %d)", a, b);
    foreach (k; x[a .. b]) {
      if (!ba[k]) {
        ba[k] = true;
        ++sz;
      }
    }
  }
  void del (const int a, const int b) {
    foreach (k; x[a .. b]) {
      //assert (freq[k] > 0, format!"freq[%d] = %d" (k, freq[k]));
      if (ba[k]) {
        ba[k] = false;
        --sz;
      }
    }
  }
  int[] processQueries (in MoQuery[] queries) {
    l = 0;
    r = -1;
    auto nq = queries.length;
    auto n = reduce!max(queries.map!(t => t.v));
    auto s = bsr (n);
    auto x = queries.map!(q => hilbert (q.u, q.v, s, 0)).array;
    auto idx = uninitializedArray!(size_t[]) (nq);
    makeIndex (x, idx);
    auto res = uninitializedArray!(R[]) (nq);
    foreach (j; idx) {
      res[j] = move (queries[j]);
    }
    return res;
  }
  this (in uint[] a, int n) {
    x = a.idup;
    //CUSTOM
    ba.length = n;
  }
}

alias ST = SegmentTree!(uint[], mrg, []);

void test (in int n, uint[] a) {
  debug stderr.writeln ("a = ", a);
  auto v = new int[n];
  foreach (i; 0 .. n) {
    v[i] = i;
  }
  auto prev = uninitializedArray!(int[]) (n);

  MoQuery[] q;

  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      q ~= MoQuery (prev[j] + 1, i.to!int - 1);
    }
    prev[j] = pos;
  }
  foreach (i; 0 .. n) {
    q ~= MoQuery (prev[i] + 1, a.length.to!int - 1);
  }

  auto solve = new MoRange (a, n);
  auto res = solve.processQueries (q);

  int cur;
  prev[] = -1;
  foreach (i, j; a) {
    immutable int pos = i.to!int;
    if (prev[j] >= 0) {
      auto k = res[cur++];
      v[j] = max (v[j], k);
    }
    prev[j] = pos;
  }
  foreach (i; 0 .. n) {
    auto k = res[cur++];
    v[i] = max (v[i], k);
  }

  foreach (i; 0 .. n) {
    int j = v[i];
    int u = i;
    if (prev[i] >= n) {
      u = 0;
    }
    writeln (u + 1, ' ', j + 1);
  }
}

void main() {
  auto r = new InputReader ();
  immutable n = r.next!uint;
  immutable m = r.next!uint;
  auto a = r.nextA!uint (m);
  foreach (i; 0 .. m) --a[i];
  auto b = new uint[n];
  foreach (i; 0 .. n) b[i] = n - 1 - i;
  b ~= a;
  a = b;
  b = null;
  a.length -= uniq (a).copy (a).length;
  test (n, a);
}


//ahmat
import core.stdc.stdio:scanf,printf,puts;
import core.bitop;
import std.stdio;
import std.string;
import std.algorithm;
import std.functional;
import std.array;
import std.container;
import std.conv;
import std.container;
import std.typecons;
import std.math;
import std.numeric;
pragma(inline,true);

void main(){
    int n=readln.chomp
                .to!int;
    int a,b;
    string s;
    bool r=false;
    while(n--){
        readf!"%s %d %d"(s,a,b);
        readln;
        if(a>=2400 && b>a){
            r=true;
            break;
        }
    }
    writeln(r?"YES":"NO");
}

module _template;
import std.stdio;
import std.string;
import std.algorithm;
import std.container;
import std.range;
import std.math;
import std.numeric;
import std.conv;
import std.typecons;
import std.format;

struct IO {
        string read_string() {
                while (tokens.empty) {
                tokens = readln.split;
        }
        auto token = tokens.front;
                tokens.popFront;
                return token;
        }

        int read_int() {
                return read_string.to!int;
        }

        string[] tokens;
}

void main() {
        IO cin;
        int t = 1;
        // int t = cin.read_int;
        while (t--) {
                int n = cin.read_int;
                bool done = false;
                while (n--) {
                        string name = cin.read_string;
                        int prev_rating = cin.read_int;
                        int new_rating = cin.read_int;
                        if (prev_rating >= 2400 && new_rating > prev_rating) done = true;
                }
                if (done) writeln("YES");
                else writeln("NO");
        }
}

#!/usr/bin/env rdmd

import std.stdio;

void main() {
    int n;
    char buffer[10];
    while (readf("%d ", &n) == 1) {
        bool ok = false;
        while (n--) {
            auto s = buffer[ ];
            int before, after;
            readf("%s %d %d ", &s, &before, &after);
            if (after > before && before >= 2400)
            ok = true;
        }
        writeln(ok ? "YES" : "NO");
    }
}


import std.stdio;
import std.uni;
import std.conv;
import std.container;
import std.functional;
import std.algorithm;
import std.array;
import std.typecons;
import std.range;
import std.numeric;
import std.traits;

void main(string[] args)
{
  auto noTc = next!int;
 tcLoop: foreach(tc; 0 .. noTc)
    {
      auto n = next!int;
      auto a = next!int(n);
      auto leftCnt = new int[](n + 1);
      long caseRes = 0;
      foreach(ai; a) leftCnt[ai]++;
      foreach(k; 0 .. n)
	{
	  leftCnt[a[k]]--;
	  long crossingPairs = 0;
	  foreach_reverse(i; 0 .. k)
	    {
	      if (a[i] == a[k])
		caseRes += crossingPairs;
	      crossingPairs += leftCnt[a[i]];
	    }
	}
      caseRes.println;
    }
}

static this()
{
  popChar;
}

struct Any(T)
{
  static auto read()
  {
    static if (is(T == char))
      {
	auto res = frontChar;
	popChar;
	return res;
      }
  }
}

struct Unsigned(T)
{
  auto read()
  {
    auto res = T(0);
    while(!frontChar.isDigit) popChar;
    do
      {
	res = res * T(10) + T(frontChar - '0');
	popChar;
      }
    while(frontChar.isDigit);
    return res;
  }
}

struct Matrix(T, alias rows, alias cols)
{
  T[][] _cell;
  alias _cell this;
  // Ring constructor
  this(int n)
  {
    final switch(n)
      {
      case 0:
	_cell = new T[][](rows, cols);
	break;
      case 1:
	debug assert(rows == cols);
	_cell = new T[][](rows, cols);
	foreach(i; 0 .. rows)
	  _cell[i][i] = T(1);
	break;
      }
  }
  // Copy constructor
  this(Matrix!(T, rows, cols) other)
  {
    _cell = new T[][](rows, cols);
    foreach(i; 0 .. rows)
      _cell[i][] = other[i][];
  }
  auto opBinary(string op)(Matrix!(T, rows, cols) other)
       if (op == "+" || op == "-")
	 {
	   auto res = Matrix!(T, rows, cols)(0);
	   foreach(i; 0 .. rows)
	     foreach(j; 0 .. cols)
	       res[i][j] = mixin(q{this[i][j]}, op, q{other[i][j]});
	   return res;
	 }
  auto opBinary(string op, alias otherRows, alias otherCols)(Matrix!(T, otherRows, otherCols) other)
       if (op == "*")
	 {
	   debug assert(cols == otherRows);
	   auto res = Matrix!(T, rows, otherCols)(0);
	   foreach(i; 0 .. rows)
	     foreach(k; 0 .. cols)
	       foreach(j; 0 .. otherCols)
		 res[i][j] += this[i][k] * other[k][j];
	   return res;
	 }
  ref auto opOpAssign(string op)(Matrix!(T, rows, cols) other)
  {
    static if (op == "*")
      {
	debug assert(rows == cols);
	alias n = rows;
	auto res = Matrix!(T, n, n)(0);
	T factor;
	foreach(i; 0 .. n)
	  foreach(k; 0 .. n)
	    foreach(j; 0 .. n)
	      res[i][j] += this[i][k] * other[k][j];
	foreach(i; 0 .. n)
	  this[i][] = res[i][];
      }
    else
      {
	foreach(i; 0 .. rows)
	  foreach(j; 0 .. cols)
	    mixin(q{this[i][j] }, text(op, q{=}), q{ other[i][j];});
      }
    return this;
  }
  mixin powMethod;
}

struct Mod(T, alias mod)
{
  alias This = Mod!(T, mod);
  T _rep;
  this(T t)
  {
    _rep = t % mod;
    if (_rep < 0) _rep += mod;
  }
  static auto plain(T t)
  {
    auto res = Mod!(T, mod)();
    res._rep = t;
    return res;
  }
  static auto fromPositive(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod).plain(t % mod);
  }
  static auto fromNegative(T t)
  {
    pragma(inline, true);
    return Mod!(T, mod).plain(t % mod + mod);
  }
  string toString()
  {
    return to!string(_rep);
  }
  debug invariant
  {
    assert(_rep >= 0 && _rep < mod);
  }
  auto opBinary(string op)(This b)
  {
    static if (op == "+")
      {
	T resrep = _rep + b._rep;
	if (resrep >= mod) resrep -= mod;
	return This.plain(resrep);
      }
    else static if (op == "-")
      {
	T resrep = _rep - b._rep;
	if (resrep < 0) resrep += mod;
	return This.plain(resrep);
      }
    else static if (op == "*")
      {
	return This.fromPositive(_rep * b._rep);
      }
  }
  auto opOpAssign(string op)(This b)
  {
    mixin(q{_rep }, text(op, "="), q{b._rep;});
    static if (op == "+")
      {
	if (_rep >= mod) _rep -= mod;
      }
    else static if (op == "-")
      {
	if (_rep < 0) _rep += mod;
      }
    else static if (op == "*")
      {
	_rep %= mod;
      }
    return this;
  }

  auto opBinary(string op)(long exp)
       if (op == "^^")
	 {
	   return pow(exp);
	 }
  mixin powMethod;
}

mixin template powMethod()
{
  auto pow(this ThisType)(long exp)
    {
      auto res = ThisType(1);
      auto pow = ThisType(this);
      while(exp)
	{
	  if (exp & 1) res *= pow;
	  pow *= pow;
	  exp >>= 1;
	}
      return res;
    }
}
// INPUT
char frontChar;
void popChar()
{
  import core.stdc.stdio;
  frontChar = cast(char) getchar;
  if (feof(stdin)) frontChar = ' ';
}
auto makeArray(T, S...)(S s)
{
  enum brackets = () {
    string res;
    foreach(i; 0 .. s.length)
      res ~= "[]";
    return res;
  } ();
  mixin(q{alias Type = T}, brackets, q{;});
  return new Type(s);
}
template isNumberLike(T)
{
  enum isNumberLike = is(typeof((){T test; test = test + test * test; test *= test;}()));
}
void popWhite()
{
  import std.ascii;
  while (frontChar.isWhite) popChar;
}
void print(T...)(T t)
{
  static foreach(ti; t)
    {
      static if (is(typeof(ti) == string))
	{
	  write(ti, " ");
	}
      else static if (isArray!(typeof(ti)))
	{
	  foreach(e; ti) print(e);
	}
      else static if (isTuple!(typeof(ti)))
	{
	  static foreach(i; ti.length) writesp(ti[i]);
	}
      else
	{
	  write(ti, " ");
	}
    }
}
void println(T...)(T t)
{
  static if (t.length == 0)
    writeln;
  static foreach(ti; t)
    {
      print(ti);
      writeln;
    }
}
auto next(alias T, S...)(S s)
{
  pragma(inline, true);
  static if (s.length > 0)
    {
      auto res = makeArray!(typeof(next!T()))(s);
      S t;
      enum loops = () {
	string res;
	foreach(i; 0 .. s.length)
	  {
	    auto ti = text(q{t[}, i, q{]});
	    res ~= text(q{for(}, ti, q{ = 0;}, ti , q{ < s[}, i, q{];}, ti, q{++)});
	  }
	return res;
      } ();
      enum indexing = () {
	string res = "res";
	foreach(i; 0 .. s.length)
	  res ~= text(q{[t[}, i, q{]]});
	return res;
      } ();
      mixin(loops, indexing, q{ = next!T;});
      return res;
    }
  else
    {
      static if (isNumberLike!T)
	{
	  import std.ascii: isDigit;
	  T res;
	  while(frontChar.isWhite) popChar;
	  T multiplier = T(1);
	  if (frontChar == '-')
	    {
	      multiplier = T(-1);
	      popChar;
	    }
	  else if (frontChar == '+')
	    {
	      popChar;
	    }
	  debug assert(frontChar.isDigit);
	  do
	    {
	      res = res * T(10) + T(frontChar - '0');
	      popChar;
	    }
	  while(frontChar.isDigit);
	  return multiplier * res;
	}
      else static if (is(T == string))
	{
	  import std.ascii: isWhite;
	  string res;
	  while(frontChar.isWhite)
	    popChar;
	  while(!frontChar.isWhite)
	    {
	      res ~= frontChar;
	      popChar;
	    }
	  return res;
	}
      else static if (is(T == char))
	{
	  while(frontChar.isWhite) popChar;
	  auto res = frontChar;
	  popChar;
	  return res;
	}
      else
	{
	  return T.read;
	}
    }
}

import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;

void main ()
{
	foreach (test; 0..readln.strip.to !(int))
	{
		auto n = readln.strip.to !(int);
		auto a = readln.splitter.map !(to !(int)).array;
		auto num = new int [] [] (n, n + 1);
		foreach (i; 0..n)
		{
			foreach (j; 0..n)
			{
				num[i][j + 1] = num[i][j] + (a[i] == a[j]);
			}
		}
		long res = 0;
		foreach (i; 1..n)
		{
			foreach (j; i + 1..n - 1)
			{
				res += num[j][i] *
				    (num[i][n] - num[i][j + 1]);
			}
		}
		writeln (res);
	}
}


import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;

void main ()
{
	auto tests = readln.strip.to !(int);
	foreach (test; 0..tests)
	{
		auto n = readln.strip.to !(int);
		auto s = readln.strip.map !(q{a == '+'}).array;

		int res = 0;
		foreach (i; 0..n)
		{
			int balance = 0;
			int pairs = 0;
			int add = 0;
			foreach (j; i..n)
			{
				if (s[j])
				{
					balance += 1;
					add = 0;
				}
				else
				{
					balance -= 1;
					add += 1;
					if (add == 2)
					{
						add = 0;
						pairs += 1;
					}
				}
				if (balance <= 0 && balance + pairs * 3 >= 0 &&
				    balance % 3 == 0)
				{
					res += 1;
				}
			}
		}

		writeln (res);
	}
}

import std.stdio;
import std.math;
import std.numeric;
import std.container;
import std.typecons;
import core.stdc.stdio : scanf;
import std.conv;
import std.array;
import std.string;
import std.range;
import std.algorithm;

T read(T)() { return readln.chomp.to!T; }
T[] readarray(T)() { return readln.chomp.split(" ").map!(to!T).array; }

void solve() {
    int N = read!int;
    auto S = readln.chomp;
    auto plus = new int[][](N, N+1);
    auto minus = new int[][](N, N+1);
    for (int l = 0; l < N; l++) {
        for (int r = l; r < N; r++) {
            plus[l][r + 1] = plus[l][r] + (S[r] == '+');
            minus[l][r + 1] = minus[l][r] + (S[r] == '-');
        }
    }
    auto cm = new int[][](N, N+1);
    for (int l = 0; l < N; l++) {
        for (int r = l; r + 1 < N; r++) {
            cm[l][r + 2] = max(cm[l][r + 1], cm[l][r] + (S[r] == '-' && S[r + 1] == '-'));
        }
    }
    int ans = 0;
    for (int l = 0; l < N; l++) {
        for (int r = l + 1; r <= N; r++) {
            int d = minus[l][r] - plus[l][r];
            if (d < 0) continue;
            if (d % 3 == 0) ans++;
        }
    }
    writeln(ans);
}

void main() {
    int T = read!int;
    foreach (t; 0 .. T) solve();
}