#include <bits/stdc++.h>
using namespace std;
template <typename T, typename T1>
T amax(T &a, T1 b) {
  if (b > a) a = b;
  return a;
}
template <typename T, typename T1>
T amin(T &a, T1 b) {
  if (b < a) a = b;
  return a;
}
template <typename T1, typename T2>
std::istream &operator>>(std::istream &in, pair<T1, T2> &a) {
  in >> a.first >> a.second;
  return in;
}
template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &out, pair<T1, T2> &a) {
  out << a.first << " " << a.second;
  return out;
}
const long long N = 2e5 + 5;
const long long maxn = N;
struct node {
  long long a[9];
  long long b[9];
  void assign(long long val) {
    long long v = val;
    for (long long i = 0; i < 9; i++) {
      if (v % 10)
        a[i] = val;
      else
        a[i] = 1000000007;
      b[i] = 1000000007;
      v /= 10;
    }
  }
  void merge(node &l, node &r) {
    long long c[4];
    for (long long i = 0; i < 9; i++) {
      c[0] = l.a[i], c[1] = l.b[i], c[2] = r.a[i], c[3] = r.b[i];
      sort(c, c + 4);
      a[i] = c[0];
      b[i] = c[1];
    }
  }
} zero;
struct segtree {
  node t[4 * maxn];

 public:
  void build(long long a[], long long v, long long tl, long long tr) {
    if (tl == tr) {
      t[v].assign(a[tl]);
      return;
    } else {
      long long tm = (tl + tr) / 2;
      build(a, v * 2, tl, tm);
      build(a, v * 2 + 1, tm + 1, tr);
      t[v].merge(t[v * 2], t[v * 2 + 1]);
    }
  }
  void build(long long a[]) { build(a, 1, 0, maxn - 1); }
  node query(long long v, long long tl, long long tr, long long l,
             long long r) {
    if (l > tr || r < tl) return zero;
    if (l <= tl && tr <= r) {
      return t[v];
    }
    long long tm = (tl + tr) / 2;
    node a, b, ans;
    a = query(v * 2, tl, tm, l, r);
    b = query(v * 2 + 1, tm + 1, tr, l, r);
    ans.merge(a, b);
    return ans;
  }
  node query(long long l, long long r) { return query(1, 0, maxn - 1, l, r); }
  void rupd(long long v, long long tl, long long tr, long long l, long long r,
            long long val) {
    if (l > tr || r < tl) return;
    if (l <= tl && tr <= r) {
      t[v].assign(val);
      return;
    }
    long long tm = (tl + tr) / 2;
    rupd(v * 2, tl, tm, l, r, val);
    rupd(v * 2 + 1, tm + 1, tr, l, r, val);
    t[v].merge(t[v * 2], t[v * 2 + 1]);
  }
  void rupd(long long l, long long val) { rupd(1, 0, maxn - 1, l, l, val); }
} t;
long long a[N];
void solve() {
  for (long long i = 0; i < 9; i++) {
    zero.a[i] = zero.b[i] = 1000000007;
  }
  long long n, m;
  cin >> n >> m;
  for (long long i = 1; i < n + 1; i++) cin >> a[i];
  t.build(a);
  for (long long i = 0; i < m; i++) {
    long long c, x, y;
    cin >> c >> x >> y;
    if (c == 1) {
      t.rupd(x, y);
    } else {
      node ans = t.query(x, y);
      long long k = 2 * 1000000007;
      for (long long i = 0; i < 9; i++) {
        if (ans.b[i] != 1000000007) amin(k, ans.a[i] + ans.b[i]);
      }
      if (k == 2 * 1000000007) k = -1;
      cout << k << "\n";
    }
  }
}
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  long long t = 1;
  while (t--) solve();
  return 0;
}
