#include <bits/stdc++.h>
using namespace std;
const long long M = 2e5 + 10;
const long long maxn = 1e5;
long long n, a[M], q;
struct segment_tree {
  struct tree {
    long long tl, tr, val, tag1, tag2;
  } t[M << 2];
  void pushup(long long k) {
    t[(k)].val = t[((k << 1))].val + t[((k << 1 | 1))].val;
  }
  void pushdown(long long k) {
    if (t[(k)].tag1) {
      t[((k << 1))].tag1 = t[((k << 1 | 1))].tag1 = t[(k)].tag1;
      t[((k << 1))].val =
          (t[((k << 1))].tr - t[((k << 1))].tl + 1) * t[(k)].tag1;
      t[((k << 1 | 1))].val =
          (t[((k << 1 | 1))].tr - t[((k << 1 | 1))].tl + 1) * t[(k)].tag1;
      t[((k << 1))].tag2 = t[((k << 1 | 1))].tag2 = 0;
      t[(k)].tag1 = 0;
    }
    if (t[(k)].tag2) {
      t[((k << 1))].tag2 ^= 1, t[((k << 1 | 1))].tag2 ^= 1,
          t[((k << 1))].val *= -1, t[((k << 1 | 1))].val *= -1;
      t[(k)].tag2 = 0;
    }
  }
  void build(long long k, long long l, long long r) {
    t[(k)].tl = l, t[(k)].tr = r;
    t[(k)].val = 1;
    if (l == r) {
      t[(k)].val = 1;
      return;
    }
    long long Mid = (l + r) >> 1;
    build((k << 1), l, Mid), build((k << 1 | 1), Mid + 1, r);
    pushup(k);
  }
  void update1(long long k, long long l, long long r, long long z) {
    if (t[(k)].tl > r || t[(k)].tr < l) return;
    if (t[(k)].tl >= l && t[(k)].tr <= r) {
      t[(k)].tag1 = z, t[(k)].val = z * (t[(k)].tr - t[(k)].tl + 1);
      t[(k)].tag2 = 0;
      return;
    }
    pushdown(k);
    update1((k << 1), l, r, z), update1((k << 1 | 1), l, r, z);
    pushup(k);
  }
  void update2(long long k, long long l, long long r) {
    if (t[(k)].tl > r || t[(k)].tr < l) return;
    if (t[(k)].tl >= l && t[(k)].tr <= r) {
      t[(k)].tag2 ^= 1, t[(k)].val *= -1;
      return;
    }
    pushdown(k);
    update2((k << 1), l, r), update2((k << 1 | 1), l, r);
    pushup(k);
  }
  long long query(long long k, long long l) {
    if (t[(k)].tl > l || t[(k)].tr < l) return 0;
    if (t[(k)].tl == l && t[(k)].tr == l) return t[(k)].val;
    pushdown(k);
    return query((k << 1), l) + query((k << 1 | 1), l);
  }
} T;
signed main() {
  cin >> n >> q;
  for (long long i = 1; i <= n; i++) cin >> a[i];
  T.build(1, 1, maxn * 2 + 1);
  while (q--) {
    string s;
    cin >> s;
    long long x;
    cin >> x;
    if (s == ">") {
      if (x >= 0) {
        T.update1(1, 1, maxn - x, 1);
        T.update1(1, 2 + maxn + x, maxn * 2 + 1, -1);
      } else {
        T.update1(1, 1, maxn + 1 + x, 1);
        T.update1(1, 1 + maxn - x, maxn * 2 + 1, -1);
        T.update2(1, maxn + 2 + x, maxn - x);
      }
    } else {
      if (x >= 0) {
        T.update2(1, maxn + 2 - x, maxn + x);
        T.update1(1, 1, maxn + 1 - x, -1);
        T.update1(1, 1 + maxn + x, maxn * 2 + 1, 1);
      } else {
        T.update1(1, 1, maxn + x, -1);
        T.update1(1, 2 + maxn - x, maxn * 2 + 1, 1);
      }
    }
  }
  for (long long i = 1; i <= n; i++)
    cout << a[i] * T.query(1, a[i] + maxn + 1) << ' ';
  return 0;
}
