#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10, inf = 2e9 + 1;
struct node {
  int mn[10], mn2[10];
  node operator+(const node& t) const {
    node tmp;
    for (int i = 0; i < 10; i++) {
      tmp.mn[i] = min(mn[i], t.mn[i]);
      if (mn[i] < t.mn[i])
        tmp.mn2[i] = min(t.mn[i], mn2[i]);
      else if (mn[i] > t.mn[i])
        tmp.mn2[i] = min(mn[i], t.mn2[i]);
      else
        tmp.mn2[i] = mn[i];
    }
    return tmp;
  }
} tree[maxn * 4];
int a[maxn];
void up(int o, int l, int r, int k, int v) {
  if (l == r) {
    for (int i = 0; i < 10; i++) tree[o].mn[i] = tree[o].mn2[i] = inf;
    int x = v, p = 0;
    while (v) {
      if (v % 10) tree[o].mn[p] = x;
      v /= 10;
      p++;
    }
    return;
  }
  if (k <= (l + r) / 2)
    up(o * 2, l, (l + r) / 2, k, v);
  else
    up(o * 2 + 1, (l + r) / 2 + 1, r, k, v);
  tree[o] = tree[o * 2] + tree[o * 2 + 1];
}
node qu(int o, int l, int r, int ql, int qr) {
  if (l >= ql && r <= qr) return tree[o];
  if (qr <= (l + r) / 2)
    return qu(o * 2, l, (l + r) / 2, ql, qr);
  else if (ql > (l + r) / 2)
    return qu(o * 2 + 1, (l + r) / 2 + 1, r, ql, qr);
  else
    return qu(o * 2, l, (l + r) / 2, ql, qr) +
           qu(o * 2 + 1, (l + r) / 2 + 1, r, ql, qr);
}
int main() {
  int n, q, x, opt, l, r;
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
    up(1, 1, n, i, a[i]);
  }
  while (q--) {
    scanf("%d%d%d", &opt, &l, &r);
    if (opt == 1)
      up(1, 1, n, l, r);
    else {
      long long ans = inf;
      node tmp = qu(1, 1, n, l, r);
      for (int i = 0; i < 10; i++) ans = min(ans, 1ll * tmp.mn[i] + tmp.mn2[i]);
      if (ans >= inf) ans = -1;
      printf("%lld\n", ans);
    }
  }
}
