Problem: Two integer sequences existed initially — one of them was strictly increasing, and the other one — strictly decreasing.

Strictly increasing sequence is a sequence of integers [x_1 < x_2 < ... < x_k]. And strictly decreasing sequence is a sequence of integers [y_1 > y_2 > ... > y_l]. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

They were merged into one sequence a. After that sequence a got shuffled. For example, some of the possible resulting sequences a for an increasing sequence [1, 3, 4] and a decreasing sequence [10, 4, 2] are sequences [1, 2, 3, 4, 4, 10] or [4, 2, 1, 10, 4, 3].

This shuffled sequence a is given in the input.

Your task is to find any two suitable initial sequences. One of them should be strictly increasing and the other one — strictly decreasing. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

If there is a contradiction in the input and it is impossible to split the given sequence a to increasing and decreasing sequences, print "NO".

Input

The first line of the input contains one integer n (1 ≤ n ≤ 2 ⋅ 10^5) — the number of elements in a.

The second line of the input contains n integers a_1, a_2, ..., a_n (0 ≤ a_i ≤ 2 ⋅ 10^5), where a_i is the i-th element of a.

Output

If there is a contradiction in the input and it is impossible to split the given sequence a to increasing and decreasing sequences, print "NO" in the first line.

Otherwise print "YES" in the first line and any two suitable sequences. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

In the second line print n_i — the number of elements in the strictly increasing sequence. n_i can be zero, in this case the increasing sequence is empty.

In the third line print n_i integers inc_1, inc_2, ..., inc_{n_i} in the increasing order of its values (inc_1 < inc_2 < ... < inc_{n_i}) — the strictly increasing sequence itself. You can keep this line empty if n_i = 0 (or just print the empty line).

In the fourth line print n_d — the number of elements in the strictly decreasing sequence. n_d can be zero, in this case the decreasing sequence is empty.

In the fifth line print n_d integers dec_1, dec_2, ..., dec_{n_d} in the decreasing order of its values (dec_1 > dec_2 > ... > dec_{n_d}) — the strictly decreasing sequence itself. You can keep this line empty if n_d = 0 (or just print the empty line).

n_i + n_d should be equal to n and the union of printed sequences should be a permutation of the given sequence (in case of "YES" answer).

Examples

Input


7
7 2 7 3 3 1 4


Output


YES
2
3 7 
5
7 4 3 2 1 


Input


5
4 3 1 5 3


Output


YES
1
3 
4
5 4 3 1 


Input


5
1 1 2 1 2


Output


NO


Input


5
0 1 2 3 4


Output


YES
0

5
4 3 2 1 0 

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
const int next_x[8] = {0, 1, -1, 0, 1, 1, -1, -1};
const int next_y[8] = {1, 0, 0, -1, 1, -1, -1, 1};
const int inf = 2147483640;
const long long long_inf = 1e15;
template <size_t size>
struct union_find_set {
  int fa[size];
  void init(int n) {
    for (int i = 1; i <= n; i++) fa[i] = i;
  }
  union_find_set() { init(size - 1); }
  int find_fa(int x) { return x == fa[x] ? x : fa[x] = find_fa(x); }
  void merge(int x, int y) {
    x = find_fa(x), y = find_fa(y);
    if (x != y) fa[x] = y;
  }
  bool same_fa(int x, int y) { return find_fa(x) == find_fa(y); }
};
template <class hash_type, int mod>
struct hash_talbe {
  int m, *a;
  hash_type s[mod + 1];
  void set_argvs(int a[], int n) { this->a = a, m = n; }
  int hash(string s) {
    int t = 0;
    const int &n = s.length();
    for (int i = 0; i < n; i++) t = t * m + a[s[i]];
    return abs(t) % mod;
  }
  void clear() { memset(s, 0, sizeof(s)); }
  hash_type &operator[](string t) { return s[hash(t)]; }
};
struct edge {
  int next, to, from;
  bool flag;
  long long w;
  edge(int a = 0, int b = 0, long long c = 0, int d = 0) {
    this->from = a;
    this->to = b;
    this->w = c;
    this->next = d;
  }
  bool operator<(const edge &o) { return w < o.w; }
};
struct graph {
  int n, m, ecnt;
  int *pre;
  edge *e;
  void add_edge(int u, int v, long long w, bool two_way) {
    ecnt++;
    e[ecnt].next = pre[u];
    e[ecnt].from = u;
    e[ecnt].to = v;
    e[ecnt].w = w;
    pre[u] = ecnt;
    if (two_way) this->add_edge(v, u, w, 0);
    return;
  }
  void init(int n, int m, int p[], edge *e) {
    this->ecnt = 0;
    this->n = n;
    this->m = m;
    this->pre = p;
    this->e = e;
    memset(pre, 0, sizeof(int) * (n + 1));
  }
  void debug() {
    printf("Graph Debug info:\n");
    for (int i = 1; i <= n; i++) printf("pre[%d]:%d\n", i, pre[i]);
    for (int i = 1; i <= ecnt; i++)
      printf("[%d] to:%d next:%d w:%d\n", i, e[i].to, e[i].next, e[i].w);
    for (int u = 1; u <= n; u++)
      for (int i = pre[u]; i; i = e[i].next)
        printf("%d->%d next:%d w:%d\n", u, e[i].to, e[i].next, e[i].w);
    printf("-----------\n");
  }
};
template <size_t size>
long long kruskal(graph G, union_find_set<size> u) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  long long ans = 0;
  sort(e + 1, e + 1 + m);
  for (int i = 1; i <= m; i++) {
    int &from = e[i].from, &to = e[i].to;
    long long &w = e[i].w;
    if (!(u.same_fa(from, to))) u.merge(from, to), ans += w;
  }
  return ans;
}
void dijkstra(graph G, priority_queue<pair<int, int> > q, int from, int dis[],
              const int &inf) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  for (int i = 1; i <= n; i++) dis[i] = inf;
  dis[from] = 0;
  q.push(make_pair(0, from));
  while (!q.empty()) {
    int u = q.top().second, dis_u = -q.top().first;
    q.pop();
    for (int i = pre[u]; i; i = e[i].next) {
      int v = e[i].to, w = e[i].w;
      if (dis_u != dis[u]) continue;
      if (dis_u + w < dis[v]) {
        dis[v] = dis_u + w;
        q.push(make_pair(-dis[v], v));
      }
    }
  }
  return;
}
template <size_t size>
void floyd(int n, int a[size][size], int dis[size][size]) {
  for (int k = 1; k <= n; k++)
    for (int i = 1; i <= n; i++)
      for (int j = 1; j <= n; j++)
        dis[i][j] =
            dis[i][k] + a[k][j] < dis[i][j] ? dis[i][k] + a[k][j] : dis[i][j];
}
void spfa(graph G, queue<int> q, int from, int dis[], bool vis[],
          const int &inf) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  for (int i = 1; i <= n; i++) dis[i] = inf;
  dis[from] = 0;
  vis[from] = 1;
  q.push(from);
  while (!q.empty()) {
    int u = q.front();
    for (int i = pre[u]; i; i = e[i].next) {
      int &v = e[i].to;
      if (dis[u] + e[i].w < dis[v]) {
        dis[v] = dis[u] + e[i].w;
        if (!vis[v]) q.push(v), vis[v] = 1;
      }
    }
    q.pop(), vis[u] = 0;
  }
  return;
}
void tarjan_work(graph G, int u, bool vis[], int bel[], int dfn[], int low[],
                 stack<int> &S, int &cnt, int &bel_cnt) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  dfn[u] = low[u] = ++cnt;
  S.push(u), vis[u] = 1;
  for (int i = pre[u]; i; i = e[i].next) {
    int &v = e[i].to;
    if (!dfn[v]) {
      tarjan_work(G, v, vis, bel, dfn, low, S, cnt, bel_cnt);
      low[u] = min(low[u], low[v]);
    } else if (vis[v])
      low[u] = min(low[u], dfn[v]);
  }
  if (dfn[u] == low[u]) {
    ++bel_cnt;
    int cur;
    do {
      cur = S.top();
      bel[cur] = bel_cnt;
      vis[cur] = 0;
      S.pop();
    } while (cur != u);
  }
}
void tarjan_work(graph &G, int u, int dfn[], int low[], int fa[], int &cnt) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  dfn[u] = low[u] = ++cnt;
  for (int i = pre[u]; i; i = e[i].next) {
    int &v = e[i].to;
    if (!dfn[v]) {
      fa[v] = u;
      tarjan_work(G, v, dfn, low, fa, cnt);
      low[u] = min(low[u], low[v]);
      if (fa[u] <= 0) fa[u]--;
    } else if (fa[u] != v)
      low[u] = min(low[u], dfn[v]);
  }
}
int tarjan(graph &G, bool vis[], int bel[], int dfn[], int low[],
           stack<int> &S) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  int cnt = 0, bel_cnt = 0;
  memset(vis, 0, sizeof(bool) * (n + 1));
  memset(bel, 0, sizeof(int) * (n + 1));
  memset(low, 0, sizeof(int) * (n + 1));
  memset(dfn, 0, sizeof(int) * (n + 1));
  while (!S.empty()) S.pop();
  for (int i = 1; i <= n; i++)
    if (!dfn[i]) tarjan_work(G, i, vis, bel, dfn, low, S, cnt, bel_cnt);
  return bel_cnt;
}
struct tarjan_counter {
  graph *G;
  int *fa, *dfn, *low;
  void debug() {
    for (int i = 1; i <= G->n; i++)
      printf("[%d] fa:%d dfn:%d low:%d\n", i, fa[i], dfn[i], low[i]);
  }
  tarjan_counter(int *fa, int *dfn, int *low, graph *G) {
    this->fa = fa;
    this->dfn = dfn;
    this->low = low;
    this->G = G;
  }
  set<int> count_cut_points() {
    edge *e = G->e;
    int &n = G->n, &m = G->m;
    int *pre = G->pre;
    set<int> ans;
    for (int v = 1; v <= n; v++) {
      int &u = fa[v];
      if (u <= -2)
        ans.insert(v);
      else if (u > 0 && fa[u] >= 0 && low[v] >= dfn[u])
        ans.insert(u);
    }
    return ans;
  }
  vector<pair<int, int> > count_bridges() {
    edge *e = G->e;
    int &n = G->n, &m = G->m;
    int *pre = G->pre;
    vector<pair<int, int> > ans;
    for (int v = 1; v <= n; v++) {
      int u = fa[v];
      if (u > 0 && low[v] > dfn[u]) {
        int cnt = 0;
        for (int i = pre[u]; i; i = e[i].next)
          if (e[i].to == v) cnt++;
        if (cnt >= 2) continue;
        pair<int, int> t = make_pair(u, v);
        ans.push_back(t);
      }
    }
    return ans;
  }
};
tarjan_counter tarjan(graph &G, int dfn[], int low[], int fa[]) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  int cnt = 0;
  memset(fa, 0, sizeof(int) * (n + 1));
  memset(low, 0, sizeof(int) * (n + 1));
  memset(dfn, 0, sizeof(int) * (n + 1));
  for (int i = 1; i <= n; i++)
    if (!dfn[i]) tarjan_work(G, i, dfn, low, fa, cnt);
  return tarjan_counter(fa, dfn, low, &G);
}
vector<int> tarjan_rebuild_graph(graph &G, int fa[]) {
  int &n = G.n, &m = G.m;
  vector<int> roots;
  G.init(n, m, G.pre, G.e);
  for (int i = 1; i <= n; i++) {
    if (fa[i] > 0)
      G.add_edge(fa[i], i, 0, 1);
    else
      roots.push_back(i);
  }
  return roots;
}
void find_ebcc_dfs(graph &G, int u, int bel[], int &bcc_cnt) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  bel[u] = bcc_cnt;
  for (int i = pre[u]; i; i = e[i].next) {
    int &v = e[i].to;
    if (!e[i].flag && !bel[v]) find_ebcc_dfs(G, v, bel, bcc_cnt);
  }
  return;
}
int find_ebcc(graph &G, vector<pair<int, int> > bridges, int bel[]) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  memset(bel, 0, sizeof(int) * (n + 1));
  for (vector<pair<int, int> >::iterator i = bridges.begin();
       i != bridges.end(); i++) {
    int u = i->first, v = i->second;
    for (int i = pre[u]; i; i = e[i].next) {
      int to = e[i].to;
      if (to == v) e[i].flag = 1;
    }
    for (int i = pre[v]; i; i = e[i].next) {
      int to = e[i].to;
      if (to == u) e[i].flag = 1;
    }
  }
  int bcc_cnt = 0;
  for (int i = 1; i <= n; i++)
    if (!bel[i]) bcc_cnt++, find_ebcc_dfs(G, i, bel, bcc_cnt);
  return bcc_cnt;
}
template <int sz1, int sz2>
struct lca {
  graph *G;
  int (*f)[sz2], *deep;
  lca(graph *G, int fa[sz1][sz2], int deep[]) {
    this->G = G;
    this->f = fa;
    this->deep = deep;
  }
  void dfs(int u, int father) {
    edge *e = G->e;
    int &n = G->n, &m = G->m;
    int *pre = G->pre;
    for (int i = pre[u]; i; i = e[i].next) {
      int &v = e[i].to;
      if (v == father)
        continue;
      else {
        deep[v] = deep[u] + 1;
        f[v][0] = u;
        dfs(v, u);
      }
    }
  }
  void init(int root) {
    int &n = G->n, &m = G->m;
    memset(deep, 0, sizeof(int) * (n + 1));
    memset(f, 0, sizeof(int) * (sz1) * (sz2));
    deep[root] = 1, dfs(root, 0);
    for (int j = 1; j < sz2; j++)
      for (int i = 1; i <= n; i++)
        if (f[i][j - 1]) f[i][j] = f[f[i][j - 1]][j - 1];
  }
  int get_lca(int u, int v) {
    if (deep[u] < deep[v]) swap(u, v);
    int t = log2(deep[u]);
    for (int i = t; i >= 0; i--) {
      if (deep[f[u][i]] >= deep[v]) u = f[u][i];
    }
    if (u == v) return u;
    for (int i = t; i >= 0; i--)
      if (f[v][i] && f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
    return f[u][0];
  }
};
void get_tree_dia_dfs(graph &G, bool vis[], int f[], int u, int &ans) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  int a = 0, b = 0;
  vis[u] = 1;
  for (int i = pre[u]; i; i = e[i].next) {
    int &v = e[i].to, w = e[i].w;
    if (vis[v]) continue;
    get_tree_dia_dfs(G, vis, f, v, ans);
    if (f[v] + w > a)
      b = a, a = f[v] + w;
    else if (f[v] + w > b)
      b = f[v] + w;
  }
  f[u] = a, ans = max(ans, a + b);
}
int get_tree_dia(graph &G, bool vis[], int f[]) {
  edge *e = G.e;
  int &n = G.n, &m = G.m;
  int *pre = G.pre;
  int ans = 0;
  memset(f, 0, sizeof(int) * (n + 1));
  memset(vis, 0, sizeof(bool) * (n + 1));
  get_tree_dia_dfs(G, vis, f, 1, ans);
  return ans;
}
template <class T>
T fast_pow(T x, T k, T m) {
  T ans = 1;
  while (k) {
    if (k % 2 == 1) ans = ans * x % m;
    k = k / 2;
    x = x * x % m;
  }
  return ans;
}
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
int exgcd(int a, int b, int &x, int &y) {
  if (b == 0) {
    x = 1, y = 0;
    return a;
  }
  int d = exgcd(b, a % b, x, y);
  int t = x;
  x = y;
  y = t - a / b * y;
  return d;
}
bool exgcd_work(int a, int b, int &x, int &y, int c) {
  int g = exgcd(a, b, x, y);
  int _a = a / g, _b = b / g;
  if (c % g != 0) return 0;
  while (x <= 0) x += _a, y += _b;
  x *= c / g, y *= c / g;
  return 1;
}
template <class T>
T muti_gcd(T a[], int n) {
  T ans = a[1];
  for (int i = 2; i <= n; i++) ans = gcd(ans, a[i]);
  return ans;
}
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }
template <size_t row_size, size_t col_size>
void gauss(int a[row_size][col_size], int n, int m) {}
void init_prime(bool not_prime[], int prime[], int &head, int n) {
  not_prime[1] = 1;
  for (int i = 2; i <= n; i++) {
    if (!not_prime[i]) prime[++head] = i;
    for (int j = 1; j <= head && (long long)prime[j] * i <= n; j++) {
      not_prime[prime[j] * i] = 1;
      if (i % prime[j] == 0) break;
    }
  }
}
bool is_prime(int x) {
  int t = sqrt(x);
  for (int i = 2; i <= t; i++)
    if (x % i == 0) return 0;
  return 1;
}
int crt(int n, int a[], int m[]) {
  int d = 1, x, y, ans = 0;
  for (int i = 1; i <= n; i++) d = d * m[i];
  for (int i = 1; i <= n; i++) {
    int M = d / m[i];
    exgcd(M, m[i], x, y);
    ans = (ans + M * x * a[i]) % d;
  }
  if (ans < 0) ans += d;
  return ans;
}
int get_phi(int n) {
  int ans = n, t = sqrt(n);
  for (int i = 2; i <= t; i++) {
    if (n % i == 0) {
      ans -= ans / i;
      while (n % i == 0) n /= i;
    }
  }
  if (n > 1) ans -= ans / n;
  return ans;
}
int init_phi() { return -1; }
long long euler(long long a, string b, long long m) {
  bool flag = 0;
  long long t = 0, phi_m = get_phi(m);
  for (string::iterator p = b.begin(); p != b.end(); p++) {
    t = t * 10 + (*p) - '0';
    if (t >= phi_m) t %= phi_m, flag = 1;
  }
  return flag ? fast_pow(a, t % phi_m + phi_m, m) : fast_pow(a, t, m);
}
struct tire_node {
  int cnt;
  int tag;
  tire_node *(nx[26]);
  tire_node() {
    tag = cnt = 0;
    memset(nx, 0, sizeof(nx));
  }
  void create(char c) { nx[c - 'a'] = new tire_node; }
  bool have_next(char c) { return nx[c - 'a'] == NULL; }
  tire_node *next(char c) { return nx[c - 'a']; }
  void release() {
    for (int i = 0; i < 26; i++)
      if (nx[i] != NULL) nx[i]->release();
    delete this;
  }
  void remove_sons() {
    for (int i = 0; i < 26; i++)
      if (nx[i] != NULL) nx[i]->release(), nx[i] = NULL;
    return;
  }
  void update() {
    cnt = tag;
    for (int i = 0; i < 26; i++)
      if (nx[i] != NULL) cnt += nx[i]->cnt;
    return;
  }
};
template <bool repeat_count>
struct tire {
  tire_node *root;
  tire() { root = new tire_node; }
  void init() {
    root->remove_sons();
    delete root;
    root = new tire_node;
  }
  void insert_work(tire_node *cur, const string &s, int index) {
    if (index == s.length()) {
      if (repeat_count)
        cur->tag++;
      else
        cur->tag = 1;
      cur->update();
      return;
    } else {
      if (cur->next(s[index]) == NULL) cur->create(s[index]);
      insert_work(cur->next(s[index]), s, index + 1);
      cur->update();
    }
  }
  void insert(string s) { insert_work(root, s, 0); }
  void del_work(tire_node *cur, const string &s, int index) {
    if (index == s.length()) {
      cur->remove_sons();
      cur->tag = cur->cnt = 0;
      return;
    } else {
      if (cur->next(s[index]) == NULL)
        return;
      else
        del_work(cur->next(s[index]), s, index + 1), cur->update();
    }
    return;
  }
  void del(string s) { del_work(root, s, 0); }
  int count(string s) {
    tire_node *cur = root;
    for (string::iterator p = s.begin(); p != s.end(); p++) {
      char t = *p;
      if (cur->next(t) == NULL) return 0;
      cur = cur->next(t);
    }
    return cur->cnt;
  }
  bool search(string s) { return count(s) > 0; }
};
template <size_t size>
struct KMP {
  string s;
  int *a, len;
  int nx[size];
  void init() { memset(nx, 0, sizeof(size)); }
  KMP() { init(); }
  void build_next(int a[], int n) {
    int k = 0;
    nx[0] = nx[1] = 0;
    for (int i = 1; i < n; i++) {
      while (k && a[i] != a[k]) k = nx[k];
      if (a[i] == a[k]) k++;
      nx[i + 1] = k;
    }
    this->a = a, this->len = n;
  }
  void build_next(string a) {
    int k = 0, n = a.length();
    nx[0] = nx[1] = 0;
    for (int i = 1; i < n; i++) {
      while (k && a[i] != a[k]) k = nx[k];
      if (a[i] == a[k]) k++;
      nx[i + 1] = k;
    }
    this->s = a, this->len = a.length();
  }
  int match(int b[], int m) {
    int k = 0;
    for (int j = 0; j < m; j++) {
      while (k && b[j] != a[k]) k = nx[k];
      if (b[j] == a[k]) k++;
      if (k == len) return j - len + 1;
    }
    return -1;
  }
  bool match(string b) {
    int k = 0, m = b.length();
    for (int j = 0; j < m; j++) {
      while (k && b[j] != s[k]) k = nx[k];
      if (b[j] == s[k]) k++;
      if (k == len) return j - len + 1;
    }
    return -1;
  }
  int get_min_loop_seq(int length) {
    return length % (length - nx[length]) == 0 ? length / (length - nx[length])
                                               : 0;
  }
  void debug() {
    for (int i = 0; i <= len; i++) printf("nx[%d] = %d\n", i, nx[i]);
  }
};
struct ACM {};
typedef bool (*checker)(int mid);
int binary_search_result(int l, int r, checker func) {
  int mid, ans = l;
  while (l <= r) {
    mid = (l + r) >> 1;
    if (func(mid))
      ans = mid, l = mid + 1;
    else
      r = mid - 1;
  }
  return ans;
}
int readin() {
  int t = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    t = t * 10 + ch - '0';
    ch = getchar();
  }
  return t * f;
}
extern const int MAXN = 200005;
extern const int N = 8000;
int n;
int a[MAXN], ans[MAXN];
void work() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  int inc = -inf, dec = inf;
  for (int i = 1; i <= n; i++) {
    if (a[i] >= dec && a[i] <= inc) {
      printf("NO\n");
      return;
    }
    if (a[i] > inc && a[i] < dec) {
      if (a[i + 1] > a[i])
        inc = a[i], ans[i] = 0;
      else
        dec = a[i], ans[i] = 1;
    } else if (a[i] > inc)
      inc = a[i], ans[i] = 0;
    else if (a[i] < dec)
      dec = a[i], ans[i] = 1;
  }
  printf("YES\n");
  for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
}
int main() {
  work();
  return 0;
}