1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <cstdio>
#include <random>
#include <cstring>
#include <cassert>
#include <set>
#include <algorithm>

using int64 = long long;

const int N = 1e5 + 10;

struct SegmentTree {
  int u[N], n;
  void init(int _n) {
    n = _n;
    memset(u, 0, sizeof(*u) * n);
  }
  void add_low(int x, int v) {
    for (; x >= 0; x -= ~x & x + 1) {
      u[x] = std::max(u[x], v);
    }
  }
  int get_low(int x, int r = 0) {
    for (; x < n; x += ~x & x + 1) {
      r = std::max(r, u[x]);
    }
    return r;
  }
  void add_upp(int x, int v) {
    for (; x < n; x += ~x & x + 1) {
      u[x] = std::max(u[x], v);
    }
  }
  int get_upp(int x, int r = 0) {
    for (; x >= 0; x -= ~x & x + 1) {
      r = std::max(r, u[x]);
    }
    return r;
  }
} low, upp;

std::set<int> row[N], col[N];
int64 queue[N * 20];
int n, m, k;

int main() {
  scanf("%d%d%d", &n, &m, &k);
  low.init(m);
  upp.init(m);
  for (int i = 0; i < n; ++i) row[i].clear();
  for (int i = 0; i < m; ++i) col[i].clear();
  int x = 0;
  for (int i = 0; i < k; ++i) {
    int r, c, z;
    scanf("%d%d%d", &r, &c, &z);
    r = (r ^ x) % n;
    c = (c ^ x) % m;
    int h_low = n - 1 - r, h_upp = r;
    bool touch_low = false, touch_upp = false;
    int lc = low.get_low(c), uc = upp.get_upp(c);
    if (lc == h_low) touch_low = true;
    else if (lc > h_low) touch_low = false;
    else if (c == 0 || low.get_low(c - 1) >= h_low) touch_low = true;
    if (uc == h_upp) touch_upp = true;
    else if (uc > h_upp) touch_upp = false;
    else if (c == m - 1 || upp.get_upp(c + 1) >= h_upp) touch_upp = true;
    if (lc <= h_low && uc <= h_upp) {
      if (lc + uc + 1 >= n) touch_low = touch_upp = 1;
    }
    if (touch_low && touch_upp) puts("TAK"), x ^= z;
    else {
      puts("NIE");
      if (!touch_low && !touch_upp) {
        row[r].insert(c);
        col[c].insert(r);
        continue;
      }
      int head = 0, tail = 0;
      queue[tail++] = (int64)r * m + c;
      for (; head < tail; ++head) {
        r = queue[head] / m, c = queue[head] % m;
        if (touch_low) {
          int h = low.get_low(c);
          if (h >= n - r) continue;
          low.add_low(c, n - r);
          auto &s = row[r - 1];
          for (auto it = s.begin(); it != s.end(); ) {
            if (*it > c + 1) break;
            queue[tail++] = (int64)(r - 1) * m + *it;
            col[*it].erase(r - 1);
            it = s.erase(it);
          }
          auto &t = col[c + 1];
          auto it = t.lower_bound(r - 1);
          for (; it != t.end(); ) {
            queue[tail++] = (int64)*it * m + c + 1;
            row[*it].erase(c + 1);
            it = t.erase(it);
          }
        } else {
          int h = upp.get_upp(c);
          if (h >= r + 1) continue;
          upp.add_upp(c, r + 1);
          auto s = col[c - 1];
          for (auto it = s.begin(); it != s.end(); ) {
            if (*it > r + 1) break;
            queue[tail++] = (int64)*it * m + c - 1;
            row[*it].erase(c - 1);
            it = s.erase(it);
          }
          auto t = row[r + 1];
          auto it = t.lower_bound(c - 1);
          for (; it != t.end(); ) {
            queue[tail++] = (int64)(r + 1) * m + *it;
            col[*it].erase(r + 1);
            it = t.erase(it);
          }
        }
      }
    }
  }
  return 0;
}