#include <bits/stdc++.h>
// created [2020/03/21] 16:00:34
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wsign-conversion"

using i32   = int32_t;
using i64   = int64_t;
using u32   = uint32_t;
using u64   = uint64_t;
using uint  = unsigned int;
using usize = std::size_t;
using ll    = long long;
using ull   = unsigned long long;
using ld    = long double;
template<typename T, usize n>
using arr = T (&)[n];
template<typename T, usize n>
using c_arr = const T (&)[n];
template<typename T>
using max_heap = std::priority_queue<T>;
template<typename T>
using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template<typename T> constexpr T popcount(const T u) { return u ? static_cast<T>(__builtin_popcountll(static_cast<u64>(u))) : static_cast<T>(0); }
template<typename T> constexpr T log2p1(const T u) { return u ? static_cast<T>(64 - __builtin_clzll(static_cast<u64>(u))) : static_cast<T>(0); }
template<typename T> constexpr T msbp1(const T u) { return log2p1(u); }
template<typename T> constexpr T lsbp1(const T u) { return __builtin_ffsll(u); }
template<typename T> constexpr T clog(const T u) { return u ? log2p1(u - 1) : static_cast<T>(u); }
template<typename T> constexpr bool ispow2(const T u) { return u and (static_cast<u64>(u) & static_cast<u64>(u - 1)) == 0; }
template<typename T> constexpr T ceil2(const T u) { return static_cast<T>(1) << clog(u); }
template<typename T> constexpr T floor2(const T u) { return u == 0 ? static_cast<T>(0) : static_cast<T>(1) << (log2p1(u) - 1); }
template<typename T> constexpr bool btest(const T mask, const usize ind) { return static_cast<bool>((static_cast<u64>(mask) >> ind) & static_cast<u64>(1)); }
template<typename T> void bset(T& mask, const usize ind) { mask |= (static_cast<T>(1) << ind); }
template<typename T> void breset(T& mask, const usize ind) { mask &= ~(static_cast<T>(1) << ind); }
template<typename T> void bflip(T& mask, const usize ind) { mask ^= (static_cast<T>(1) << ind); }
template<typename T> void bset(T& mask, const usize ind, const bool b) { (b ? bset(mask, ind) : breset(mask, ind)); }
template<typename T> constexpr T bcut(const T mask, const usize ind) { return ind == 0 ? static_cast<T>(0) : static_cast<T>((static_cast<u64>(mask) << (64 - ind)) >> (64 - ind)); }
template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
constexpr unsigned int mod                  = 1000000007;
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};
auto mfp = [](auto&& f) { return [=](auto&&... args) { return f(f, std::forward<decltype(args)>(args)...); }; };

template<typename T>
T in()
{
    T v;
    return std::cin >> v, v;
}
template<typename T, typename Uint, usize n, usize i>
T in_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type) { return in<T>(); }
template<typename T, typename Uint, usize n, usize i>
auto in_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type& szs)
{
    const usize s = (usize)szs[i];
    std::vector<decltype(in_v<T, Uint, n, i + 1>(szs))> ans(s);
    for (usize j = 0; j < s; j++) { ans[j] = in_v<T, Uint, n, i + 1>(szs); }
    return ans;
}
template<typename T, typename Uint, usize n>
auto in_v(c_arr<Uint, n> szs) { return in_v<T, Uint, n, 0>(szs); }
template<typename... Types>
auto in_t() { return std::tuple<std::decay_t<Types>...>{in<Types>()...}; }
struct io_init
{
    io_init()
    {
        std::cin.tie(nullptr), std::ios::sync_with_stdio(false);
        std::cout << std::fixed << std::setprecision(20);
    }
    void clear()
    {
        std::cin.tie(), std::ios::sync_with_stdio(true);
    }
} io_setting;

int out() { return 0; }
template<typename T>
int out(const T& v) { return std::cout << v, 0; }
template<typename T>
int out(const std::vector<T>& v)
{
    for (usize i = 0; i < v.size(); i++) {
        if (i > 0) { std::cout << ' '; }
        out(v[i]);
    }
    return 0;
}
template<typename T1, typename T2>
int out(const std::pair<T1, T2>& v) { return out(v.first), std::cout << ' ', out(v.second), 0; }
template<typename T, typename... Args>
int out(const T& v, const Args... args) { return out(v), std::cout << ' ', out(args...), 0; }
template<typename... Args>
int outln(const Args... args) { return out(args...), std::cout << '\n', 0; }
template<typename... Args>
int outel(const Args... args) { return out(args...), std::cout << std::endl, 0; }
#    define SHOW(...) static_cast<void>(0)
constexpr ull TEN(const usize n) { return n == 0 ? 1ULL : TEN(n - 1) * 10ULL; }

template<typename T, typename Uint, usize n, usize i>
auto make_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type, const T& v = T{}) { return v; }
template<typename T, typename Uint, usize n, usize i>
auto make_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type szs, const T& v = T{})
{
    const usize s = (usize)szs[i];
    return std::vector<decltype(make_v<T, Uint, n, i + 1>(szs, v))>(s, make_v<T, Uint, n, i + 1>(szs, v));
}
template<typename T, typename Uint, usize n>
auto make_v(c_arr<Uint, n> szs, const T& t = T{}) { return make_v<T, Uint, n, 0>(szs, t); }

template<typename Cost = usize>
struct edge
{
    using cost_type = Cost;
    usize u, v;
    Cost c;
    edge(const usize u, const usize v) : u{u}, v{v}, c{1} {}
    edge(const usize u, const usize v, const Cost& c) : u{u}, v{v}, c{c} {}
    operator usize() const { return v; }
    usize from() const { return u; }
    usize to() const { return v; }
    Cost cost() const { return c; }
    friend std::ostream& operator<<(std::ostream& os, const edge& e) { return os << e.u << "->" << e.v << ":" << e.c; }
};
template<typename Edge>
class base_graph
{
public:
    base_graph(const usize n) : v{n}, es(n), res(n) {}
    void add_edge(const usize u, const usize v, const bool bi = false)
    {
        es[u].emplace_back(u, v), res[v].emplace_back(v, u);
        if (bi) { es[v].emplace_back(v, u), res[u].emplace_back(u, v); }
    }
    template<typename Cost>
    void add_edge(const usize u, const usize v, const Cost& c, const bool bi = false)
    {
        es[u].emplace_back(u, v, c), res[v].emplace_back(v, u, c);
        if (bi) { es[v].emplace_back(v, u, c), res[u].emplace_back(u, v, c); }
    }
    std::vector<Edge>& operator[](const usize u) { return es[u]; }
    const std::vector<Edge>& operator[](const usize u) const { return es[u]; }
    std::vector<Edge>& from(const usize u) { return es[u]; }
    const std::vector<Edge>& from(const usize u) const { return es[u]; }
    std::vector<Edge>& to(const usize v) { return res[v]; }
    const std::vector<Edge>& to(const usize v) const { return res[v]; }
    usize size() const { return v; }
    friend std::ostream& operator<<(std::ostream& os, const base_graph& g)
    {
        for (usize i = 0; i < g.v; i++) {
            for (const auto& e : g.es[i]) { os << e << '\n'; }
        }
        return os;
    }

private:
    usize v;
    std::vector<std::vector<Edge>> es, res;
};
template<typename Edge>
using base_tree = base_graph<Edge>;
using graph     = base_graph<edge<>>;
using tree      = base_graph<edge<>>;
template<typename Cost>
using cost_graph = base_graph<edge<Cost>>;
template<typename Cost>
using cost_tree = base_graph<edge<Cost>>;
template<typename Edge = edge<>>
class hl_decomp
{
public:
    hl_decomp(base_tree<Edge>& tree, const usize r = 0) : par(tree.size(), tree.size()), top{par}, in{par}, rin{par}, out{par}
    {
        const usize n = tree.size();
        std::vector<usize> sz(n, 1);
        auto dfs1 = [&](auto&& self, const usize s, const usize p) -> usize {
            par[s] = p;
            for (auto& e : tree[s]) {
                const usize to = e.to();
                if (p == to) { continue; }
                sz[s] += self(self, to, s);
                if (sz[to] > sz[tree[s][0].to()]) { std::swap(e, tree[s].front()); }
            }
            return sz[s];
        };
        dfs1(dfs1, r, n);
        top[r]    = r;
        auto dfs2 = [&](auto&& self, const usize s, const usize p, usize& ind) -> void {
            in[s] = ind++, rin[in[s]] = s;
            for (const auto& e : tree[s]) {
                const usize to = e.to();
                if (to == p) { continue; }
                top[to] = (to == tree[s][0].to() ? top[s] : to);
                self(self, to, s, ind);
            }
            out[s] = ind;
        };
        usize ind = 0;
        dfs2(dfs2, r, n, ind);
    }
    usize pos(const usize v) const { return in[v]; }
    usize at(const usize n) const { return rin[n]; }
    std::pair<usize, usize> sub(const usize v) const { return {in[v], out[v]}; }
    std::vector<std::pair<usize, usize>> path(usize u, usize v, const bool edgeWeight = false) const
    {
        using P = std::pair<usize, usize>;
        std::vector<P> head, tail;
        for (usize pu = top[u], pv = top[v]; pu != pv;) {
            if (in[pu] < in[pv]) {
                tail.push_back({in[pv], in[v]});
                v = par[pv], pv = top[v];
            } else {
                tail.push_back({in[u], in[pu]});
                u = par[pu], pu = top[u];
            }
        }
        if (edgeWeight) {
            if (std::abs((int)in[u] - (int)in[v]) >= 1) { head.push_back(in[u] < in[v] ? P{in[u] + 1, in[v]} : P{in[u], in[v] + 1}); }
        } else {
            head.push_back({in[u], in[v]});
        }
        std::reverse(tail.begin(), tail.end());
        for (const auto& p : tail) { head.push_back(p); }
        return head;
    }
    friend std::ostream& operator<<(std::ostream& os, const hl_decomp& hld)
    {
        os << "{";
        for (const usize v : hld.rin()) { os << v << ","; }
        return os << "}";
    }

private:
    std::vector<usize> par, top, in, rin, out;
};

template<typename ValueMonoid>
class segtree
{
public:
    using value_monoid_type = ValueMonoid;
    using value_type        = typename value_monoid_type::value_type;
    segtree(const usize sz, const value_type initial = value_monoid_type::id()) : sz{sz}, half{ceil2(sz)}, val(half << 1, value_monoid_type::id())
    {
        if (initial != value_monoid_type::id()) {
            std::fill(val.begin() + half, val.end(), initial);
            for (usize i = half - 1; i >= 1; i--) { up(i); }
        }
    }
    template<typename InIt>
    segtree(const InIt first, const InIt last) : sz{static_cast<usize>(std::distance(first, last))}, half{ceil2(sz)}, val(half << 1, value_monoid_type::id())
    {
        std::copy(first, last, val.begin() + half);
        for (usize i = half - 1; i >= 1; i--) { up(i); }
    }
    value_type get(const usize a) const { return assert(a < sz), val[a + half]; }
    void set(usize a, const value_type& v)
    {
        assert(a < sz);
        val[a += half] = v;
        while (a >>= 1) { up(a); }
    }
    value_type fold(usize l, usize r) const
    {
        assert(l < r), assert(r <= sz);
        value_type accl = value_monoid_type::id(), accr = value_monoid_type::id();
        for (l += half, r += half; l < r; l >>= 1, r >>= 1) {
            if (l & 1) { accl = value_monoid_type::merge(accl, val[l++]); }
            if (r & 1) { accr = value_monoid_type::merge(val[--r], accr); }
        }
        return value_monoid_type::merge(accl, accr);
    }
    usize size() const { return sz; }
    friend std::ostream& operator<<(std::ostream& os, const segtree& seg)
    {
        os << "[";
        for (usize i = seg.half; i < seg.half + seg.sz; i++) { os << seg.val[i] << (i + 1 == seg.half + seg.sz ? "" : ","); }
        return (os << "]\n");
    }

private:
    void up(const usize i) { val[i] = value_monoid_type::merge(val[i << 1], val[i << 1 | 1]); }
    const usize sz, half;
    std::vector<value_type> val;
};
template<typename Element>
struct sum
{
    using element_type = Element;
    using value_type   = element_type;
    sum()              = delete;
    static value_type merge(const value_type& a, const value_type& b) { return a + b; }
    static constexpr value_type id() { return value_type{}; }
};
int main()
{
    const auto [N, Q] = in_t<int, int>();
    const auto as     = in_v<ll>({N});
    graph g(N);
    for (int i = 0; i < N - 1; i++) {
        const auto u = in<int>() - 1, v = in<int>() - 1;
        g.add_edge(u, v, true);
    }
    std::vector<ll> coeff(N, 1);
    mfp([&](auto&& self, const int s, const int p) -> void {
        for (const int to : g[s]) {
            if (to == p) { continue; }
            self(self, to, s);
            coeff[to] = -coeff[s];
        }
    });
    hl_decomp hld(g);
    segtree<sum<ll>> seg(N, 0LL);
    for (int i = 0; i < Q; i++) {
        const auto t = in<int>();
        if (t == 1) {
            const auto x  = in<int>() - 1;
            const auto v  = in<ll>();
            const int pos = hld.pos(x);
            seg.set(pos, seg.get(pos) + coeff[x] * v);
        } else {
            const auto x  = in<int>() - 1;
            const auto ps = hld.path(x, 0);
            for (const auto& p : ps) {
                int l = p.first, r = p.second;
                if (l > r) { std::swap(l, r); }
                r++;
                const ll sum = seg.fold(l, r);
                outln(coeff[x] * sum);
            }
        }
    }
    return 0;
}


#include <bits/stdc++.h>
// created [2020/03/21] 16:00:34
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wsign-conversion"

using i32   = int32_t;
using i64   = int64_t;
using u32   = uint32_t;
using u64   = uint64_t;
using uint  = unsigned int;
using usize = std::size_t;
using ll    = long long;
using ull   = unsigned long long;
using ld    = long double;
template<typename T, usize n>
using arr = T (&)[n];
template<typename T, usize n>
using c_arr = const T (&)[n];
template<typename T>
using max_heap = std::priority_queue<T>;
template<typename T>
using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template<typename T> constexpr T popcount(const T u) { return u ? static_cast<T>(__builtin_popcountll(static_cast<u64>(u))) : static_cast<T>(0); }
template<typename T> constexpr T log2p1(const T u) { return u ? static_cast<T>(64 - __builtin_clzll(static_cast<u64>(u))) : static_cast<T>(0); }
template<typename T> constexpr T msbp1(const T u) { return log2p1(u); }
template<typename T> constexpr T lsbp1(const T u) { return __builtin_ffsll(u); }
template<typename T> constexpr T clog(const T u) { return u ? log2p1(u - 1) : static_cast<T>(u); }
template<typename T> constexpr bool ispow2(const T u) { return u and (static_cast<u64>(u) & static_cast<u64>(u - 1)) == 0; }
template<typename T> constexpr T ceil2(const T u) { return static_cast<T>(1) << clog(u); }
template<typename T> constexpr T floor2(const T u) { return u == 0 ? static_cast<T>(0) : static_cast<T>(1) << (log2p1(u) - 1); }
template<typename T> constexpr bool btest(const T mask, const usize ind) { return static_cast<bool>((static_cast<u64>(mask) >> ind) & static_cast<u64>(1)); }
template<typename T> void bset(T& mask, const usize ind) { mask |= (static_cast<T>(1) << ind); }
template<typename T> void breset(T& mask, const usize ind) { mask &= ~(static_cast<T>(1) << ind); }
template<typename T> void bflip(T& mask, const usize ind) { mask ^= (static_cast<T>(1) << ind); }
template<typename T> void bset(T& mask, const usize ind, const bool b) { (b ? bset(mask, ind) : breset(mask, ind)); }
template<typename T> constexpr T bcut(const T mask, const usize ind) { return ind == 0 ? static_cast<T>(0) : static_cast<T>((static_cast<u64>(mask) << (64 - ind)) >> (64 - ind)); }
template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
constexpr unsigned int mod                  = 1000000007;
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};
auto mfp = [](auto&& f) { return [=](auto&&... args) { return f(f, std::forward<decltype(args)>(args)...); }; };

template<typename T>
T in()
{
    T v;
    return std::cin >> v, v;
}
template<typename T, typename Uint, usize n, usize i>
T in_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type) { return in<T>(); }
template<typename T, typename Uint, usize n, usize i>
auto in_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type& szs)
{
    const usize s = (usize)szs[i];
    std::vector<decltype(in_v<T, Uint, n, i + 1>(szs))> ans(s);
    for (usize j = 0; j < s; j++) { ans[j] = in_v<T, Uint, n, i + 1>(szs); }
    return ans;
}
template<typename T, typename Uint, usize n>
auto in_v(c_arr<Uint, n> szs) { return in_v<T, Uint, n, 0>(szs); }
template<typename... Types>
auto in_t() { return std::tuple<std::decay_t<Types>...>{in<Types>()...}; }
struct io_init
{
    io_init()
    {
        std::cin.tie(nullptr), std::ios::sync_with_stdio(false);
        std::cout << std::fixed << std::setprecision(20);
    }
    void clear()
    {
        std::cin.tie(), std::ios::sync_with_stdio(true);
    }
} io_setting;

int out() { return 0; }
template<typename T>
int out(const T& v) { return std::cout << v, 0; }
template<typename T>
int out(const std::vector<T>& v)
{
    for (usize i = 0; i < v.size(); i++) {
        if (i > 0) { std::cout << ' '; }
        out(v[i]);
    }
    return 0;
}
template<typename T1, typename T2>
int out(const std::pair<T1, T2>& v) { return out(v.first), std::cout << ' ', out(v.second), 0; }
template<typename T, typename... Args>
int out(const T& v, const Args... args) { return out(v), std::cout << ' ', out(args...), 0; }
template<typename... Args>
int outln(const Args... args) { return out(args...), std::cout << '\n', 0; }
template<typename... Args>
int outel(const Args... args) { return out(args...), std::cout << std::endl, 0; }
#    define SHOW(...) static_cast<void>(0)
constexpr ull TEN(const usize n) { return n == 0 ? 1ULL : TEN(n - 1) * 10ULL; }

template<typename T, typename Uint, usize n, usize i>
auto make_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type, const T& v = T{}) { return v; }
template<typename T, typename Uint, usize n, usize i>
auto make_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type szs, const T& v = T{})
{
    const usize s = (usize)szs[i];
    return std::vector<decltype(make_v<T, Uint, n, i + 1>(szs, v))>(s, make_v<T, Uint, n, i + 1>(szs, v));
}
template<typename T, typename Uint, usize n>
auto make_v(c_arr<Uint, n> szs, const T& t = T{}) { return make_v<T, Uint, n, 0>(szs, t); }

template<typename Cost = usize>
struct edge
{
    using cost_type = Cost;
    usize u, v;
    Cost c;
    edge(const usize u, const usize v) : u{u}, v{v}, c{1} {}
    edge(const usize u, const usize v, const Cost& c) : u{u}, v{v}, c{c} {}
    operator usize() const { return v; }
    usize from() const { return u; }
    usize to() const { return v; }
    Cost cost() const { return c; }
    friend std::ostream& operator<<(std::ostream& os, const edge& e) { return os << e.u << "->" << e.v << ":" << e.c; }
};
template<typename Edge>
class base_graph
{
public:
    base_graph(const usize n) : v{n}, es(n), res(n) {}
    void add_edge(const usize u, const usize v, const bool bi = false)
    {
        es[u].emplace_back(u, v), res[v].emplace_back(v, u);
        if (bi) { es[v].emplace_back(v, u), res[u].emplace_back(u, v); }
    }
    template<typename Cost>
    void add_edge(const usize u, const usize v, const Cost& c, const bool bi = false)
    {
        es[u].emplace_back(u, v, c), res[v].emplace_back(v, u, c);
        if (bi) { es[v].emplace_back(v, u, c), res[u].emplace_back(u, v, c); }
    }
    std::vector<Edge>& operator[](const usize u) { return es[u]; }
    const std::vector<Edge>& operator[](const usize u) const { return es[u]; }
    std::vector<Edge>& from(const usize u) { return es[u]; }
    const std::vector<Edge>& from(const usize u) const { return es[u]; }
    std::vector<Edge>& to(const usize v) { return res[v]; }
    const std::vector<Edge>& to(const usize v) const { return res[v]; }
    usize size() const { return v; }
    friend std::ostream& operator<<(std::ostream& os, const base_graph& g)
    {
        for (usize i = 0; i < g.v; i++) {
            for (const auto& e : g.es[i]) { os << e << '\n'; }
        }
        return os;
    }

private:
    usize v;
    std::vector<std::vector<Edge>> es, res;
};
template<typename Edge>
using base_tree = base_graph<Edge>;
using graph     = base_graph<edge<>>;
using tree      = base_graph<edge<>>;
template<typename Cost>
using cost_graph = base_graph<edge<Cost>>;
template<typename Cost>
using cost_tree = base_graph<edge<Cost>>;
template<typename Edge = edge<>>
class hl_decomp
{
public:
    hl_decomp(base_tree<Edge>& tree, const usize r = 0) : par(tree.size(), tree.size()), top{par}, in{par}, rin{par}, out{par}
    {
        const usize n = tree.size();
        std::vector<usize> sz(n, 1);
        auto dfs1 = [&](auto&& self, const usize s, const usize p) -> usize {
            par[s] = p;
            for (auto& e : tree[s]) {
                const usize to = e.to();
                if (p == to) { continue; }
                sz[s] += self(self, to, s);
                if (sz[to] > sz[tree[s][0].to()]) { std::swap(e, tree[s].front()); }
            }
            return sz[s];
        };
        dfs1(dfs1, r, n);
        top[r]    = r;
        auto dfs2 = [&](auto&& self, const usize s, const usize p, usize& ind) -> void {
            in[s] = ind++, rin[in[s]] = s;
            for (const auto& e : tree[s]) {
                const usize to = e.to();
                if (to == p) { continue; }
                top[to] = (to == tree[s][0].to() ? top[s] : to);
                self(self, to, s, ind);
            }
            out[s] = ind;
        };
        usize ind = 0;
        dfs2(dfs2, r, n, ind);
    }
    usize pos(const usize v) const { return in[v]; }
    usize at(const usize n) const { return rin[n]; }
    std::pair<usize, usize> sub(const usize v) const { return {in[v], out[v]}; }
    std::vector<std::pair<usize, usize>> path(usize u, usize v, const bool edgeWeight = false) const
    {
        using P = std::pair<usize, usize>;
        std::vector<P> head, tail;
        for (usize pu = top[u], pv = top[v]; pu != pv;) {
            if (in[pu] < in[pv]) {
                tail.push_back({in[pv], in[v]});
                v = par[pv], pv = top[v];
            } else {
                tail.push_back({in[u], in[pu]});
                u = par[pu], pu = top[u];
            }
        }
        if (edgeWeight) {
            if (std::abs((int)in[u] - (int)in[v]) >= 1) { head.push_back(in[u] < in[v] ? P{in[u] + 1, in[v]} : P{in[u], in[v] + 1}); }
        } else {
            head.push_back({in[u], in[v]});
        }
        std::reverse(tail.begin(), tail.end());
        for (const auto& p : tail) { head.push_back(p); }
        return head;
    }
    friend std::ostream& operator<<(std::ostream& os, const hl_decomp& hld)
    {
        os << "{";
        for (const usize v : hld.rin()) { os << v << ","; }
        return os << "}";
    }

private:
    std::vector<usize> par, top, in, rin, out;
};

template<typename ValueMonoid>
class segtree
{
public:
    using value_monoid_type = ValueMonoid;
    using value_type        = typename value_monoid_type::value_type;
    segtree(const usize sz, const value_type initial = value_monoid_type::id()) : sz{sz}, half{ceil2(sz)}, val(half << 1, value_monoid_type::id())
    {
        if (initial != value_monoid_type::id()) {
            std::fill(val.begin() + half, val.end(), initial);
            for (usize i = half - 1; i >= 1; i--) { up(i); }
        }
    }
    template<typename InIt>
    segtree(const InIt first, const InIt last) : sz{static_cast<usize>(std::distance(first, last))}, half{ceil2(sz)}, val(half << 1, value_monoid_type::id())
    {
        std::copy(first, last, val.begin() + half);
        for (usize i = half - 1; i >= 1; i--) { up(i); }
    }
    value_type get(const usize a) const { return assert(a < sz), val[a + half]; }
    void set(usize a, const value_type& v)
    {
        assert(a < sz);
        val[a += half] = v;
        while (a >>= 1) { up(a); }
    }
    value_type fold(usize l, usize r) const
    {
        assert(l < r), assert(r <= sz);
        value_type accl = value_monoid_type::id(), accr = value_monoid_type::id();
        for (l += half, r += half; l < r; l >>= 1, r >>= 1) {
            if (l & 1) { accl = value_monoid_type::merge(accl, val[l++]); }
            if (r & 1) { accr = value_monoid_type::merge(val[--r], accr); }
        }
        return value_monoid_type::merge(accl, accr);
    }
    usize size() const { return sz; }
    friend std::ostream& operator<<(std::ostream& os, const segtree& seg)
    {
        os << "[";
        for (usize i = seg.half; i < seg.half + seg.sz; i++) { os << seg.val[i] << (i + 1 == seg.half + seg.sz ? "" : ","); }
        return (os << "]\n");
    }

private:
    void up(const usize i) { val[i] = value_monoid_type::merge(val[i << 1], val[i << 1 | 1]); }
    const usize sz, half;
    std::vector<value_type> val;
};
template<typename Element>
struct sum
{
    using element_type = Element;
    using value_type   = element_type;
    sum()              = delete;
    static value_type merge(const value_type& a, const value_type& b) { return a + b; }
    static constexpr value_type id() { return value_type{}; }
};
int main()
{
    const auto [N, Q] = in_t<int, int>();
    const auto as     = in_v<ll>({N});
    graph g(N);
    for (int i = 0; i < N - 1; i++) {
        const auto u = in<int>() - 1, v = in<int>() - 1;
        g.add_edge(u, v, true);
    }
    std::vector<ll> coeff(N, 1);
    mfp([&](auto&& self, const int s, const int p) -> void {
        for (const int to : g[s]) {
            if (to == p) { continue; }
            self(self, to, s);
            coeff[to] = -coeff[s];
        }
    });
    hl_decomp hld(g);
    segtree<sum<ll>> seg(N, 0LL);
    for (int i = 0; i < Q; i++) {
        const auto t = in<int>();
        if (t == 1) {
            const auto x  = in<int>() - 1;
            const auto v  = in<ll>();
            const int pos = hld.pos(x);
            seg.set(pos, seg.get(pos) + coeff[x] * v);
        } else {
            const auto x  = in<int>() - 1;
            const auto ps = hld.path(x, 0);
            ll sum        = 0;
            for (const auto& p : ps) {
                int l = p.first, r = p.second;
                if (l > r) { std::swap(l, r); }
                r++;
                sum += seg.fold(l, r);
            }
            outln(sum * coeff[x] + as[x]);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
// created [2020/03/21] 16:00:34
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wsign-conversion"

using i32   = int32_t;
using i64   = int64_t;
using u32   = uint32_t;
using u64   = uint64_t;
using uint  = unsigned int;
using usize = std::size_t;
using ll    = long long;
using ull   = unsigned long long;
using ld    = long double;
template<typename T, usize n>
using arr = T (&)[n];
template<typename T, usize n>
using c_arr = const T (&)[n];
template<typename T>
using max_heap = std::priority_queue<T>;
template<typename T>
using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template<typename T> constexpr T popcount(const T u) { return u ? static_cast<T>(__builtin_popcountll(static_cast<u64>(u))) : static_cast<T>(0); }
template<typename T> constexpr T log2p1(const T u) { return u ? static_cast<T>(64 - __builtin_clzll(static_cast<u64>(u))) : static_cast<T>(0); }
template<typename T> constexpr T msbp1(const T u) { return log2p1(u); }
template<typename T> constexpr T lsbp1(const T u) { return __builtin_ffsll(u); }
template<typename T> constexpr T clog(const T u) { return u ? log2p1(u - 1) : static_cast<T>(u); }
template<typename T> constexpr bool ispow2(const T u) { return u and (static_cast<u64>(u) & static_cast<u64>(u - 1)) == 0; }
template<typename T> constexpr T ceil2(const T u) { return static_cast<T>(1) << clog(u); }
template<typename T> constexpr T floor2(const T u) { return u == 0 ? static_cast<T>(0) : static_cast<T>(1) << (log2p1(u) - 1); }
template<typename T> constexpr bool btest(const T mask, const usize ind) { return static_cast<bool>((static_cast<u64>(mask) >> ind) & static_cast<u64>(1)); }
template<typename T> void bset(T& mask, const usize ind) { mask |= (static_cast<T>(1) << ind); }
template<typename T> void breset(T& mask, const usize ind) { mask &= ~(static_cast<T>(1) << ind); }
template<typename T> void bflip(T& mask, const usize ind) { mask ^= (static_cast<T>(1) << ind); }
template<typename T> void bset(T& mask, const usize ind, const bool b) { (b ? bset(mask, ind) : breset(mask, ind)); }
template<typename T> constexpr T bcut(const T mask, const usize ind) { return ind == 0 ? static_cast<T>(0) : static_cast<T>((static_cast<u64>(mask) << (64 - ind)) >> (64 - ind)); }
template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
constexpr unsigned int mod                  = 1000000007;
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};
auto mfp = [](auto&& f) { return [=](auto&&... args) { return f(f, std::forward<decltype(args)>(args)...); }; };

template<typename T>
T in()
{
    T v;
    return std::cin >> v, v;
}
template<typename T, typename Uint, usize n, usize i>
T in_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type) { return in<T>(); }
template<typename T, typename Uint, usize n, usize i>
auto in_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type& szs)
{
    const usize s = (usize)szs[i];
    std::vector<decltype(in_v<T, Uint, n, i + 1>(szs))> ans(s);
    for (usize j = 0; j < s; j++) { ans[j] = in_v<T, Uint, n, i + 1>(szs); }
    return ans;
}
template<typename T, typename Uint, usize n>
auto in_v(c_arr<Uint, n> szs) { return in_v<T, Uint, n, 0>(szs); }
template<typename... Types>
auto in_t() { return std::tuple<std::decay_t<Types>...>{in<Types>()...}; }
struct io_init
{
    io_init()
    {
        std::cin.tie(nullptr), std::ios::sync_with_stdio(false);
        std::cout << std::fixed << std::setprecision(20);
    }
    void clear()
    {
        std::cin.tie(), std::ios::sync_with_stdio(true);
    }
} io_setting;

int out() { return 0; }
template<typename T>
int out(const T& v) { return std::cout << v, 0; }
template<typename T>
int out(const std::vector<T>& v)
{
    for (usize i = 0; i < v.size(); i++) {
        if (i > 0) { std::cout << ' '; }
        out(v[i]);
    }
    return 0;
}
template<typename T1, typename T2>
int out(const std::pair<T1, T2>& v) { return out(v.first), std::cout << ' ', out(v.second), 0; }
template<typename T, typename... Args>
int out(const T& v, const Args... args) { return out(v), std::cout << ' ', out(args...), 0; }
template<typename... Args>
int outln(const Args... args) { return out(args...), std::cout << '\n', 0; }
template<typename... Args>
int outel(const Args... args) { return out(args...), std::cout << std::endl, 0; }
#    define SHOW(...) static_cast<void>(0)
constexpr ull TEN(const usize n) { return n == 0 ? 1ULL : TEN(n - 1) * 10ULL; }

template<typename T, typename Uint, usize n, usize i>
auto make_v(typename std::enable_if<(i == n), c_arr<Uint, n>>::type, const T& v = T{}) { return v; }
template<typename T, typename Uint, usize n, usize i>
auto make_v(typename std::enable_if<(i < n), c_arr<Uint, n>>::type szs, const T& v = T{})
{
    const usize s = (usize)szs[i];
    return std::vector<decltype(make_v<T, Uint, n, i + 1>(szs, v))>(s, make_v<T, Uint, n, i + 1>(szs, v));
}
template<typename T, typename Uint, usize n>
auto make_v(c_arr<Uint, n> szs, const T& t = T{}) { return make_v<T, Uint, n, 0>(szs, t); }

template<typename Cost = usize>
struct edge
{
    using cost_type = Cost;
    usize u, v;
    Cost c;
    edge(const usize u, const usize v) : u{u}, v{v}, c{1} {}
    edge(const usize u, const usize v, const Cost& c) : u{u}, v{v}, c{c} {}
    operator usize() const { return v; }
    usize from() const { return u; }
    usize to() const { return v; }
    Cost cost() const { return c; }
    friend std::ostream& operator<<(std::ostream& os, const edge& e) { return os << e.u << "->" << e.v << ":" << e.c; }
};
template<typename Edge>
class base_graph
{
public:
    base_graph(const usize n) : v{n}, es(n), res(n) {}
    void add_edge(const usize u, const usize v, const bool bi = false)
    {
        es[u].emplace_back(u, v), res[v].emplace_back(v, u);
        if (bi) { es[v].emplace_back(v, u), res[u].emplace_back(u, v); }
    }
    template<typename Cost>
    void add_edge(const usize u, const usize v, const Cost& c, const bool bi = false)
    {
        es[u].emplace_back(u, v, c), res[v].emplace_back(v, u, c);
        if (bi) { es[v].emplace_back(v, u, c), res[u].emplace_back(u, v, c); }
    }
    std::vector<Edge>& operator[](const usize u) { return es[u]; }
    const std::vector<Edge>& operator[](const usize u) const { return es[u]; }
    std::vector<Edge>& from(const usize u) { return es[u]; }
    const std::vector<Edge>& from(const usize u) const { return es[u]; }
    std::vector<Edge>& to(const usize v) { return res[v]; }
    const std::vector<Edge>& to(const usize v) const { return res[v]; }
    usize size() const { return v; }
    friend std::ostream& operator<<(std::ostream& os, const base_graph& g)
    {
        for (usize i = 0; i < g.v; i++) {
            for (const auto& e : g.es[i]) { os << e << '\n'; }
        }
        return os;
    }

private:
    usize v;
    std::vector<std::vector<Edge>> es, res;
};
template<typename Edge>
using base_tree = base_graph<Edge>;
using graph     = base_graph<edge<>>;
using tree      = base_graph<edge<>>;
template<typename Cost>
using cost_graph = base_graph<edge<Cost>>;
template<typename Cost>
using cost_tree = base_graph<edge<Cost>>;
template<typename Edge = edge<>>
class hl_decomp
{
public:
    hl_decomp(base_tree<Edge>& tree, const usize r = 0) : par(tree.size(), tree.size()), top{par}, in{par}, rin{par}, out{par}
    {
        const usize n = tree.size();
        std::vector<usize> sz(n, 1);
        auto dfs1 = [&](auto&& self, const usize s, const usize p) -> usize {
            par[s] = p;
            for (auto& e : tree[s]) {
                const usize to = e.to();
                if (p == to) { continue; }
                sz[s] += self(self, to, s);
                if (sz[to] > sz[tree[s][0].to()]) { std::swap(e, tree[s].front()); }
            }
            return sz[s];
        };
        dfs1(dfs1, r, n);
        top[r]    = r;
        auto dfs2 = [&](auto&& self, const usize s, const usize p, usize& ind) -> void {
            in[s] = ind++, rin[in[s]] = s;
            for (const auto& e : tree[s]) {
                const usize to = e.to();
                if (to == p) { continue; }
                top[to] = (to == tree[s][0].to() ? top[s] : to);
                self(self, to, s, ind);
            }
            out[s] = ind;
        };
        usize ind = 0;
        dfs2(dfs2, r, n, ind);
    }
    usize pos(const usize v) const { return in[v]; }
    usize at(const usize n) const { return rin[n]; }
    std::pair<usize, usize> sub(const usize v) const { return {in[v], out[v]}; }
    std::vector<std::pair<usize, usize>> path(usize u, usize v, const bool edgeWeight = false) const
    {
        using P = std::pair<usize, usize>;
        std::vector<P> head, tail;
        for (usize pu = top[u], pv = top[v]; pu != pv;) {
            if (in[pu] < in[pv]) {
                tail.push_back({in[pv], in[v]});
                v = par[pv], pv = top[v];
            } else {
                tail.push_back({in[u], in[pu]});
                u = par[pu], pu = top[u];
            }
        }
        if (edgeWeight) {
            if (std::abs((int)in[u] - (int)in[v]) >= 1) { head.push_back(in[u] < in[v] ? P{in[u] + 1, in[v]} : P{in[u], in[v] + 1}); }
        } else {
            head.push_back({in[u], in[v]});
        }
        std::reverse(tail.begin(), tail.end());
        for (const auto& p : tail) { head.push_back(p); }
        return head;
    }
    friend std::ostream& operator<<(std::ostream& os, const hl_decomp& hld)
    {
        os << "{";
        for (const usize v : hld.rin) { os << v << ","; }
        return os << "}";
    }

private:
    std::vector<usize> par, top, in, rin, out;
};

template<typename ValueMonoid>
class segtree
{
public:
    using value_monoid_type = ValueMonoid;
    using value_type        = typename value_monoid_type::value_type;
    segtree(const usize sz, const value_type initial = value_monoid_type::id()) : sz{sz}, half{ceil2(sz)}, val(half << 1, value_monoid_type::id())
    {
        if (initial != value_monoid_type::id()) {
            std::fill(val.begin() + half, val.end(), initial);
            for (usize i = half - 1; i >= 1; i--) { up(i); }
        }
    }
    template<typename InIt>
    segtree(const InIt first, const InIt last) : sz{static_cast<usize>(std::distance(first, last))}, half{ceil2(sz)}, val(half << 1, value_monoid_type::id())
    {
        std::copy(first, last, val.begin() + half);
        for (usize i = half - 1; i >= 1; i--) { up(i); }
    }
    value_type get(const usize a) const { return assert(a < sz), val[a + half]; }
    void set(usize a, const value_type& v)
    {
        assert(a < sz);
        val[a += half] = v;
        while (a >>= 1) { up(a); }
    }
    value_type fold(usize l, usize r) const
    {
        assert(l < r), assert(r <= sz);
        value_type accl = value_monoid_type::id(), accr = value_monoid_type::id();
        for (l += half, r += half; l < r; l >>= 1, r >>= 1) {
            if (l & 1) { accl = value_monoid_type::merge(accl, val[l++]); }
            if (r & 1) { accr = value_monoid_type::merge(val[--r], accr); }
        }
        return value_monoid_type::merge(accl, accr);
    }
    usize size() const { return sz; }
    friend std::ostream& operator<<(std::ostream& os, const segtree& seg)
    {
        os << "[";
        for (usize i = seg.half; i < seg.half + seg.sz; i++) { os << seg.val[i] << (i + 1 == seg.half + seg.sz ? "" : ","); }
        return (os << "]\n");
    }

private:
    void up(const usize i) { val[i] = value_monoid_type::merge(val[i << 1], val[i << 1 | 1]); }
    const usize sz, half;
    std::vector<value_type> val;
};
template<typename Element>
struct sum
{
    using element_type = Element;
    using value_type   = element_type;
    sum()              = delete;
    static value_type merge(const value_type& a, const value_type& b) { return a + b; }
    static constexpr value_type id() { return value_type{}; }
};
int main()
{
    const auto [N, Q] = in_t<int, int>();
    const auto as     = in_v<ll>({N});
    graph g(N);
    for (int i = 0; i < N - 1; i++) {
        const auto u = in<int>() - 1, v = in<int>() - 1;
        g.add_edge(u, v, true);
    }
    std::vector<ll> coeff(N, 1);
    mfp([&](auto&& self, const int s, const int p) -> void {
        for (const int to : g[s]) {
            if (to == p) { continue; }
            coeff[to] = -coeff[s];
            self(self, to, s);
        }
    })(0, -1);
    hl_decomp hld(g);
    segtree<sum<ll>> seg(N, 0LL);
    for (int i = 0; i < Q; i++) {
        const auto t = in<int>();
        if (t == 1) {
            const auto x  = in<int>() - 1;
            const auto v  = in<ll>();
            const int pos = hld.pos(x);
            seg.set(pos, seg.get(pos) + coeff[x] * v);
        } else {
            const auto x  = in<int>() - 1;
            const auto ps = hld.path(x, 0);
            ll sum        = 0;
            for (const auto& p : ps) {
                int l = p.first, r = p.second;
                if (l > r) { std::swap(l, r); }
                r++;
                sum += seg.fold(l, r);
            }
            outln(sum * coeff[x]+as[x]);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/rope>

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl "\n"
#define long long long
#define PI 3.141592653589793238

#define Yes(a) cout << (a ? "Yes" : "No") << endl
#define YES(a) cout << (a ? "YES" : "NO") << endl
#define POSSIBLE(a) cout << (a ? "POSSIBLE" : "IMPOSSIBLE") << endl

#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << endl;
        //use cerr if u want to display at the bottom
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define trace(...)
#endif

template<typename T> istream& operator>>(istream &is, complex<T> &vl){
  T a,b; is >> a >> b; vl = complex<T>(a,b); return is;
}
template<typename T1, typename T2> ostream& operator<<(ostream& s, const pair<T1, T2>& p){
  return s << "(" << p.first << ", " << p.second << ")";
}
template<class T> istream& operator>>(istream &is,vector<T> &st){
  for(size_t i=0;i<st.size();++i){is >> st[i];} return is;
}
template<class T> istream& operator>>(istream &is,vector<vector<T>> &st){
  for(size_t i=0;i<st.size();++i){is >> st[i];} return is;
}
template<typename T1, typename T2> istream& operator>>(istream &is,pair<T1, T2>& p){
  is >> p.first >> p.second; return is;
}
template<class T> ostream& operator<<(ostream &os, const vector<T> &st){
  for(size_t i=0;i<st.size();++i) os << st[i] << (i!=st.size()-1?" ":"");
  return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &st){
  for(auto i = st.begin();i != st.end();++i) os << *i << (i!=st.end()?" ":"");
  return os;
}
template<class T> ostream& operator<<(ostream &os, const unordered_set<T> &st){
  for(auto i = st.begin();i != st.end();++i) os << *i << (i!=st.end()?" ":"");
  return os;
}
template<typename T1, typename T2> ostream& operator<<(ostream &os, const map<T1,T2> &st){
  for(auto i = st.begin();i != st.end();++i) os << i->first <<" " << i->second << endl;
  return os;
}
template<typename T1, typename T2> ostream& operator<<(ostream &os, const unordered_map<T1,T2> &st){
  for(auto i = st.begin();i != st.end();++i) os << i->first <<" " << i->second << endl;
  return os;
}
template<> ostream& operator<<(ostream &os, const vector<string> &st){
  for(size_t i=0;i<st.size();++i) os << st[i] << (i!=st.size()-1?"\n":"");
  return os;
}
template<class T> ostream& operator<<(ostream &os, const vector<vector<T>> &st){
  for(size_t i=0;i<st.size();++i) os << st[i] << (i!=st.size()-1?"\n":"");
  return os;
}

typedef trie<string,null_type,trie_string_access_traits<>,pat_trie_tag,trie_prefix_search_node_update> pref_trie;
typedef tree<long int,null_type,less<long int>,rb_tree_tag,tree_order_statistics_node_update>ordered_set;
typedef cc_hash_table<long int,long int, hash<long int>, equal_to<long int>, direct_mask_range_hashing<long int>,
hash_standard_resize_policy<hash_exponential_size_policy<>, hash_load_check_resize_trigger<true>, true>> ht;
typedef gp_hash_table<long int,long int> HashTable;

class BIT{
    vector<long int> vec;
    public:
        BIT(){
            long int n = 2e5 + 5;
            vec.resize(n);
        }

        void update(long int idx, long int val){
            for(; idx < vec.size(); idx += idx & (-idx))
                vec[idx] += val;
        }

        long int query(long int b){
            long int result = 0;
            while(b){
                result += vec[b];
                b -= b & (-b);
            }
            return result;
        }
};

vector<vector<long int>> g;
vector<long int> v, level, start, finish;
long int n,m, t = 0;

void DFS(long int idx, long int par, long int l){
  level[idx] = (l % 2);
  start[idx] = ++t;
  for(auto ele : g[idx]){
    if(ele == par)
      continue;
    DFS(ele,idx,l + 1);
  }
  finish[idx] = t;
}

int main(){
   IOS;
 /*    #ifndef ONLINE_JUDGE
         freopen("in.txt",  "r",  stdin);
         freopen("out.txt", "w", stdout);
     #finishif */

   cin>>n>>m;
   v.resize(n);
   g.resize(n);
   start.resize(n);
   finish.resize(n);
   level.resize(n);

   cin>>v;

   for(long int i = 1; i < n; i++){
      long int a,b;
      cin>>a>>b;
      g[a - 1].push_back(b - 1);
      g[b - 1].push_back(a - 1);
   }

   DFS(0,-1,0);

   vector<BIT> trees(2);

   while(m--){
      long int type;
      cin>>type;

      if(type == 1){
        long int x,val;
        cin>>x>>val;

        long int node = x - 1;
        long int l = level[node];

        trees[l].update(start[node],val);
        trees[l].update(finish[node] + 1, -val);
        trees[l ^ 1].update(start[node], -val);
        trees[l ^ 1].update(finish[node] + 1, val);
      }
      else{
        long int x;
        cin>>x;
        long int node = x -  1;
        long int l = level[node];
        cout<<v[node] + trees[l].query(start[node])<<endl;
      }
   }

   return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/rope>

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl "\n"
#define long long long
#define PI 3.141592653589793238

#define Yes(a) cout << (a ? "Yes" : "No") << endl
#define YES(a) cout << (a ? "YES" : "NO") << endl
#define POSSIBLE(a) cout << (a ? "POSSIBLE" : "IMPOSSIBLE") << endl

#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << endl;
        //use cerr if u want to display at the bottom
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define trace(...)
#endif

template<typename T> istream& operator>>(istream &is, complex<T> &vl){
  T a,b; is >> a >> b; vl = complex<T>(a,b); return is;
}
template<typename T1, typename T2> ostream& operator<<(ostream& s, const pair<T1, T2>& p){
  return s << "(" << p.first << ", " << p.second << ")";
}
template<class T> istream& operator>>(istream &is,vector<T> &st){
  for(size_t i=0;i<st.size();++i){is >> st[i];} return is;
}
template<class T> istream& operator>>(istream &is,vector<vector<T>> &st){
  for(size_t i=0;i<st.size();++i){is >> st[i];} return is;
}
template<typename T1, typename T2> istream& operator>>(istream &is,pair<T1, T2>& p){
  is >> p.first >> p.second; return is;
}
template<class T> ostream& operator<<(ostream &os, const vector<T> &st){
  for(size_t i=0;i<st.size();++i) os << st[i] << (i!=st.size()-1?" ":"");
  return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &st){
  for(auto i = st.begin();i != st.end();++i) os << *i << (i!=st.end()?" ":"");
  return os;
}
template<class T> ostream& operator<<(ostream &os, const unordered_set<T> &st){
  for(auto i = st.begin();i != st.end();++i) os << *i << (i!=st.end()?" ":"");
  return os;
}
template<typename T1, typename T2> ostream& operator<<(ostream &os, const map<T1,T2> &st){
  for(auto i = st.begin();i != st.end();++i) os << i->first <<" " << i->second << endl;
  return os;
}
template<typename T1, typename T2> ostream& operator<<(ostream &os, const unordered_map<T1,T2> &st){
  for(auto i = st.begin();i != st.end();++i) os << i->first <<" " << i->second << endl;
  return os;
}
template<> ostream& operator<<(ostream &os, const vector<string> &st){
  for(size_t i=0;i<st.size();++i) os << st[i] << (i!=st.size()-1?"\n":"");
  return os;
}
template<class T> ostream& operator<<(ostream &os, const vector<vector<T>> &st){
  for(size_t i=0;i<st.size();++i) os << st[i] << (i!=st.size()-1?"\n":"");
  return os;
}

typedef trie<string,null_type,trie_string_access_traits<>,pat_trie_tag,trie_prefix_search_node_update> pref_trie;
typedef tree<long int,null_type,less<long int>,rb_tree_tag,tree_order_statistics_node_update>ordered_set;
typedef cc_hash_table<long int,long int, hash<long int>, equal_to<long int>, direct_mask_range_hashing<long int>,
hash_standard_resize_policy<hash_exponential_size_policy<>, hash_load_check_resize_trigger<true>, true>> ht;
typedef gp_hash_table<long int,long int> HashTable;

class BIT{
    vector<long int> vec;
    public:
        BIT(){
            long int n = 2e5 + 5;
            vec.resize(n);
        }

        void update(long int idx, long int val){
            for(; idx < vec.size(); idx += idx & (-idx))
                vec[idx] += val;
        }

        long int query(long int b){
            long int result = 0;
            while(b){
                result += vec[b];
                b -= b & (-b);
            }
            return result;
        }
};

vector<vector<long int>> g;
vector<long int> v, level, start, finish;
long int n,m, t = 0;

void DFS(long int idx, long int par, long int l){
  level[idx] = (l % 2);
  start[idx] = ++t;
  for(auto ele : g[idx]){
    if(ele == par)
      continue;
    DFS(ele,idx,l + 1);
  }
  finish[idx] = t;
}

int main(){
   IOS;
 /*    #ifndef ONLINE_JUDGE
         freopen("in.txt",  "r",  stdin);
         freopen("out.txt", "w", stdout);
     #finishif */

   cin>>n>>m;
   v.resize(n);
   g.resize(n);
   start.resize(n);
   finish.resize(n);
   level.resize(n);

   cin>>v;

   for(long int i = 1; i < m; i++){
      long int a,b;
      cin>>a>>b;
      g[a - 1].push_back(b - 1);
      g[b - 1].push_back(a - 1);
   }

   DFS(0,-1,0);

   vector<BIT> trees(2);

   while(m--){
      long int type;
      cin>>type;

      if(type == 1){
        long int x,val;
        cin>>x>>val;

        long int node = x - 1;
        long int l = level[node];

        trees[l].update(start[node],val);
        trees[l].update(finish[node] + 1, -val);
        trees[l ^ 1].update(start[node], -val);
        trees[l ^ 1].update(finish[node] + 1, val);
      }
      else{
        long int x;
        cin>>x;
        long int node = x -  1;
        long int l = level[node];
        cout<<v[node] + trees[l].query(start[node])<<endl;
      }
   }

   return 0;
}


//Author - Rahil Malhotra
#include <bits/stdc++.h>
using namespace std;

#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl '\n'
#define int long long
#define double long double

int n,m;
vector<int>v[200005];
int arr[200005];
int vis[200005];
int tim[200005][2];
int ct=1;
int lvl[200005]={};
int tree[2000005][2];
int lazy[2000005][2];
void propogate(int i,int l,int r,int idx)
{
    tree[i][idx]+=lazy[i][idx];
    if(l!=r)
        lazy[i*2][idx]+=lazy[i][idx],lazy[i*2+1][idx]+=lazy[i][idx];
    lazy[i][idx]=0;
}
void update(int i,int l,int r,int l1,int r1,int val,int idx)
{
    if(lazy[i][idx])
        propogate(i,l,r,idx);
    if(l1>r1 || l>r1 || l1>r)
        return;
    if(l1<=l && r<=r1)
    {
        tree[i][idx]+=val;
        if(l!=r)
            lazy[i*2][idx]+=val,lazy[i*2+1][idx]+=val;
        return;
    }
    int mid=(l+r)/2;
    update(i*2,l,mid,l1,r1,val,idx);
    update(i*2+1,mid+1,r,l1,r1,val,idx);
    tree[i][idx]=tree[i*2][idx]+tree[i*2+1][idx];
}
int query(int i,int l,int r,int l1,int r1,int idx)
{
    if(l1>r1 || l>r1 || l1>r)
        return 0;
    if(lazy[i][idx])
        propogate(i,l,r,idx);
    if(l1<=l && r<=r1)
        return tree[i][idx];
    int mid=(l+r)/2;
    return query(i*2,l,mid,l1,r1,idx)+query(i*2+1,mid+1,r,l1,r1,idx);
}
int dfs(int pos,int l)
{
    vis[pos]=1;
    lvl[pos]=l;

    tim[pos][0]=ct++;
    for(int j:v[pos])
        if(!vis[j])
            dfs(j,l^1);
    tim[pos][1]=ct++;
}
int32_t main()
{
    IOS;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>arr[i];
    for(int i=0;i<n-1;i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
    dfs(1,0);
    while(m--)
    {
        int a;cin>>a;
        if(a==2)
        {
            int v;
            cin>>v;
            cout<<arr[v]+query(1,1,ct,tim[v][0],tim[v][0],lvl[v])-query(1,1,ct,tim[v][0],tim[v][0],lvl[v]^1)<<endl;
        }
        else
        {
            int v,val;
            cin>>v>>val;
            update(1,1,ct,tim[v][0],tim[v][1],val,lvl[v]);
        }
    }
}


// " --- IN THE NAME OF ALLAH --- " // ;)
// ------------sphr_agz------------ // ;)
#include <bits/stdc++.h>
using namespace std;

typedef long double ld;
typedef long long int lli;
typedef pair <lli, lli> pii;
#define pb push_back
#define recout(x) return cout << (x), 0
#define f first
#define s second
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define stp(x) cout << setprecision(x) << fixed
#define mk make_pair
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops")
#pragma GCC optimize("no-stack-protector,fast-math")
const lli N = 2e5 + 10, N2 = 2e5 + 10, delta = 46639, mod = 1e9 + 7, oo = N - 1, LOG = 20;
const ld PI = 3.141592653589793;

lli sum[N << 2], cnt, st[N], fn[N], h[N], a[N];
vector <lli> v[N];

void dfs (lli x, lli par) {
	st[x] = cnt++;
	for (auto u: v[x])
		if (u != par) {
			h[u] = h[x] + 1;
			dfs (u, x);
		}
	fn[x] = cnt;
}

void add (lli l, lli r, lli val, lli b = 0, lli e = N, lli id = 1) {
	if (l <= b && e <= r) {
		sum[id] += val;
		return;
	}
	lli mid = (b + e) / 2;
	if (l < mid)
		add (l, r, val, b, mid, 2 * id);
	if (mid < r)
		add (l, r, val, mid, e, 2 * id + 1);
}

lli get1 (lli ind, lli l = 0, lli r = N, lli id = 1) {
	if (r - l <= 1)
		return sum[id];
	lli mid = (r + l) / 2, ans = sum[id];
	if (ind < mid)
		ans += get1 (ind, l, mid, 2 * id);
	else
		ans += get1 (ind, mid, r, 2 * id + 1);
	return ans;
}

lli get2 (lli ind, lli l = 0, lli r = N, lli id = 1) {
	if (r - l <= 1)
		return -sum[id];
	lli mid = (r + l) / 2, ans = -sum[id];
	if (ind < mid)
		ans += get2 (ind, l, mid, 2 * id);
	else
		ans += get2 (ind, mid, r, 2 * id + 1);
	return ans;
}

int main() {
	fast;
	lli n, q;
	cin >> n >> q;
	for (lli i = 0; i < n; i++)
		cin >> a[i];
	for (lli i = 0; i < n - 1; i++) {
		lli x, y;
		cin >> x >> y;
		x--, y--;
		v[x].pb(y);
		v[y].pb(x);
	}
	dfs (0, -1);
	while (q--) {
		lli type;
		cin >> type;
		if (type == 1) {
			lli u, val;
			cin >> u >> val;
			u--;
			if (!(h[u] % 2))
				add (st[u], fn[u], val);
			else
				add (st[u], fn[u], -val);
		}
		else {
			lli u;
			cin >> u;
			u--;
			if (!(h[u] % 2))
				cout << a[u] + get1 (st[u]) << '\n';
			else
				cout << a[u] + get2 (st[u]) << '\n';
		}
	}
	return 0;
}


#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector")
#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
#include "debug.h"
#else
#define debug(...)
#endif

#define df(b, e) ((b) > (e))
#define fore(i, b, e) for (auto i = (b) - df(b, e); i != e - df(b, e); i += 1 - 2 * df(b, e))
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second
#define pb push_back
#define eb emplace_back
#define mp make_pair

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<int> dis(1, 1000);

typedef long long lli;
typedef long double ld;
typedef pair<int, int> ii;
typedef vector<int> vi;

const int N = 2e5 + 5;
vi graph[N];
int tin[N], tout[N], tour[2 * N], dep[N];
int timer = 0;
int n, m, num[N];

void dfs(int u, int pr = 0) {
  tin[u] = ++timer;
  tour[timer] = u;
  for (int v : graph[u])
    if (v != pr) {
      dep[v] = dep[u] + 1;
      dfs(v, u);
    }
  tout[u] = timer;
}

template <class T>
struct Fenwick {
  #define lsb(x) (x & -x)
  vector<T> fenw;

  Fenwick(int n = 0) : fenw(n + 1, {}) {}

  void update(int i, T v) {
    for (; i < sz(fenw); i += lsb(i))
      fenw[i] += v;
  }

  void update(int l, int r, T val) {
    update(l, val);
    update(r + 1, -val);
  }

  T query(int i) {
    T v = {};
    for (; i > 0; i -= lsb(i))
      v += fenw[i];
    return v;
  }
};

int main() {
  cin.tie(0)->sync_with_stdio(0), cout.tie(0);
  cin >> n >> m;

  fore (i, 1, n + 1)
    cin >> num[i];

  fore (i, 0, n - 1) {
    int u, v;
    cin >> u >> v;
    graph[u].pb(v);
    graph[v].pb(u);
  }

  dfs(1);

  Fenwick<int> tree(n);

  fore (i, 0, m) {
    int op, u, val;
    cin >> op >> u;
    if (op == 1) {
      cin >> val;
      tree.update(tin[u], tout[u], dep[u] % 2 == 0 ? +val : -val);
    } else
      cout << num[u] + (dep[u] % 2 == 0 ? +tree.query(tin[u]) : -tree.query(tin[u])) << '\n';
  }
  return 0;
}


#include <bits/stdc++.h>

using std::cin;
using std::cout;
using std::string;
using std::vector;

int main() {
#ifdef _LOCAL
    freopen("input.txt", "r", stdin);
#endif
    std::ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int T;
    for (cin >> T; T--;) {
        int n, m;
        cin >> n >> m;
        vector<string> matrix(n);
        for (auto &str : matrix)
            cin >> str;
        vector<std::pair<int, int>> ans;
        auto flip = [&](int x, int y) {
            ans.emplace_back(x + 1, y + 1);
            if (matrix[x][y] == '0') matrix[x][y] = '1';
            else matrix[x][y] = '0';
        };
        for (int i = 0; i < n - 2; ++i) {
            for (int j = 0; j < m - 1; ++j) {
                if (matrix[i][j] == '0' && matrix[i][j + 1] == '0') continue;
                if (matrix[i][j] == '1' && matrix[i][j + 1] == '1') {
                    flip(i, j);
                    flip(i, j + 1);
                    flip(i + 1, j);
                }
                else if (matrix[i][j] == '1') {
                    flip(i, j);
                    flip(i + 1, j);
                    flip(i + 1, j + 1);
                }
                else {
                    flip(i, j + 1);
                    flip(i + 1, j);
                    flip(i + 1, j + 1);
                }
            }
        }
        for (int j = 0; j < m - 1; ++j) {
            if (matrix[n - 2][j] == '0' && matrix[n - 1][j] == '0') continue;
            if (matrix[n - 2][j] == '1' && matrix[n - 1][j] == '1') {
                flip(n - 2, j);
                flip(n - 1, j);
                flip(n - 2, j + 1);
            }
            else if (matrix[n - 2][j] == '1') {
                flip(n - 2, j);
                flip(n - 2, j + 1);
                flip(n - 1, j + 1);
            }
            else {
                flip(n - 1, j);
                flip(n - 2, j + 1);
                flip(n - 1, j + 1);
            }
        }
        if (matrix[n - 2][m - 1] == '1' && matrix[n - 1][m - 1] == '1') {
            flip(n - 2, m - 1);
            flip(n - 2, m - 2);
            flip(n - 1, m - 2);
            flip(n - 2, m - 2);
            flip(n - 1, m - 2);
            flip(n - 1, m - 1);
        }
        else if(matrix[n - 2][m - 1] == '0' && matrix[n - 1][m - 1] == '1') {
            flip(n - 2, m - 2);
            flip(n - 2, m - 1);
            flip(n - 1, m - 1);
            flip(n - 2, m - 2);
            flip(n - 1, m - 2);
            flip(n - 1, m - 1);
            flip(n - 2, m - 1);
            flip(n - 1, m - 2);
            flip(n - 1, m - 1);
        }
        else {
            flip(n - 1, m - 2);
            flip(n - 1, m - 1);
            flip(n - 2, m - 1);
            flip(n - 1, m - 2);
            flip(n - 2, m - 1);
            flip(n - 2, m - 2);
            flip(n - 2, m - 2);
            flip(n - 2, m - 1);
            flip(n - 1, m - 1);
        }
        cout << (int)ans.size() / 3 << '\n';
        for (int i = 0; i < ans.size(); i += 3) {
            cout << ans[i].first << ' ' << ans[i].second << ' ';
            cout << ans[i + 1].first << ' ' << ans[i + 1].second << ' ';
            cout << ans[i + 2].first << ' ' << ans[i + 2].second << '\n';
        }
    }
}


#include <bits/stdc++.h>

using i32 = int;
using i64 = long long;

i32 main() {
    std::ios::sync_with_stdio(false);
    std::cout.tie(nullptr);
    std::cin.tie(nullptr);

    i32 dis[16], prev[16];
    const i32 inf = 0x3f3f3f3f;
    memset(dis, inf, sizeof dis);
    std::vector<i32> q({0});
    dis[0] = 0;
    for (i32 i = 0; i < q.size();) {
        i32 u = q[i++];
        for (i32 j = 0; j < 4; j++) {
            i32 v = (15 ^ (1 << j)) ^ u;
            if (dis[v] == inf) {
                dis[v] = dis[u] + 1;
                prev[v] = j;
                q.push_back(v);
            }
        }
    }
    auto print1 = [&](i32 mask, i32 i, i32 j) {
        std::cout << std::bitset<4>(mask) << "\n";
        while (mask != 0) {
            i32 x = prev[mask];
            for (i32 y = 0; y < 4; y++) {
                if (y == x) continue;
                std::cout << i + (3 - y) / 2 << " " <<  j + (3 - y) % 2 << " ";
            }
            std::cout << std::endl;
            mask ^= (15 ^ (1 << x));
        }
    };
    //print1(3, 0, 0);
    i32 T;
    std::cin >> T;
    while (T--) {
        i32 n, m;
        std::cin >> n >> m;
        std::vector<std::string> a(n);
        for (i32 i = 0; i < n; i++) {
            std::cin >> a[i];
            for (i32 j = 0; j < m; j++)
                a[i][j] -= '0';
        }
        std::vector<std::pair<i32, i32>> ans;
        auto print = [&](i32 mask, i32 i, i32 j) {
            while (mask != 0) {
                i32 x = prev[mask];
                for (i32 y = 0; y < 4; y++) {
                    if (y == x) continue;
                    a[i + (3 - y) / 2][j + (3 - y) % 2] ^= 1;
                    ans.emplace_back(i + (3 - y) / 2, j + (3 - y) % 2);
                }
                mask ^= (15 ^ (1 << x));
            }
        };
        for (i32 i = 0; i + 1 < n; i++) {
            for (i32 j = 0; j + 1 < m; j++) {
                if (a[i][j] == 0) continue;
                ans.emplace_back(i, j);
                ans.emplace_back(i + 1, j);
                ans.emplace_back(i + 1, j + 1);
                a[i][j] ^= 1;
                a[i + 1][j] ^= 1;
                a[i + 1][j + 1] ^= 1;
            }
            if (a[i][m - 1] != 0) {
                ans.emplace_back(i, m - 1);
                ans.emplace_back(i + 1, m - 2);
                ans.emplace_back(i + 1, m - 1);
                a[i][m - 1] ^= 1;
                a[i + 1][m - 2] ^= 1;
                a[i + 1][m - 1] ^= 1;
            }
        }
        for (i32 j = 0; j < m; j += 2) {
            i32 mask = a[n - 1][j] * 2 + a[n - 1][j + 1];
            print(mask, n - 2, j);
        }
        if (a[n - 1][m - 1] != 0) {
            i32 mask = a[n - 1][m - 2] * 2 + a[n - 1][m - 1];
            print(mask, n - 2, m - 2);
        }
        std::cout << ans.size() / 3 << "\n";
        for (i32 i = 0; i < ans.size(); i += 3) {
            std::cout << ans[i].first + 1 << " " << ans[i].second + 1 << " ";
            std::cout << ans[i + 1].first + 1 << " " << ans[i + 1].second + 1 << " ";
            std::cout << ans[i + 2].first + 1 << " " << ans[i + 2].second + 1 << "\n";
        }
    }
    return 0;
}


#include <bits/stdc++.h>

using i32 = int;
using i64 = long long;

i32 main() {
    std::ios::sync_with_stdio(false);
    std::cout.tie(nullptr);
    std::cin.tie(nullptr);

    i32 dis[16], prev[16];
    const i32 inf = 0x3f3f3f3f;
    memset(dis, inf, sizeof dis);
    std::vector<i32> q({0});
    dis[0] = 0;
    for (i32 i = 0; i < q.size();) {
        i32 u = q[i++];
        for (i32 j = 0; j < 4; j++) {
            i32 v = (15 ^ (1 << j)) ^ u;
            if (dis[v] == inf) {
                dis[v] = dis[u] + 1;
                prev[v] = j;
                q.push_back(v);
            }
        }
    }
    auto print1 = [&](i32 mask, i32 i, i32 j) {
        std::cout << std::bitset<4>(mask) << "\n";
        while (mask != 0) {
            i32 x = prev[mask];
            for (i32 y = 0; y < 4; y++) {
                if (y == x) continue;
                std::cout << i + (3 - y) / 2 << " " <<  j + (3 - y) % 2 << " ";
            }
            std::cout << std::endl;
            mask ^= (15 ^ (1 << x));
        }
    };
    //print1(3, 0, 0);
    i32 T;
    std::cin >> T;
    while (T--) {
        i32 n, m;
        std::cin >> n >> m;
        std::vector<std::string> a(n);
        for (i32 i = 0; i < n; i++) {
            std::cin >> a[i];
            for (i32 j = 0; j < m; j++)
                a[i][j] -= '0';
        }
        std::vector<std::pair<i32, i32>> ans;
        auto print = [&](i32 mask, i32 i, i32 j) {
            while (mask != 0) {
                i32 x = prev[mask];
                for (i32 y = 0; y < 4; y++) {
                    if (y == x) continue;
                    a[i + (3 - y) / 2][j + (3 - y) % 2] ^= 1;
                    ans.emplace_back(i + (3 - y) / 2, j + (3 - y) % 2);
                }
                mask ^= (15 ^ (1 << x));
            }
        };
        for (i32 i = 0; i + 1 < n; i++) {
            for (i32 j = 0; j + 1 < m; j++) {
                if (a[i][j] == 0) continue;
                ans.emplace_back(i, j);
                ans.emplace_back(i + 1, j);
                ans.emplace_back(i + 1, j + 1);
                a[i][j] ^= 1;
                a[i + 1][j] ^= 1;
                a[i + 1][j + 1] ^= 1;
            }
            if (a[i][m - 1] != 0) {
                ans.emplace_back(i, m - 1);
                ans.emplace_back(i - 1, m - 2);
                ans.emplace_back(i - 1, m - 1);
                a[i][m - 1] ^= 1;
                a[i + 1][m - 2] ^= 1;
                a[i + 1][m - 1] ^= 1;
            }
        }
        for (i32 j = 0; j < m; j += 2) {
            i32 mask = a[n - 1][j] * 2 + a[n - 1][j + 1];
            print(mask, n - 2, j);
        }
        if (a[n - 1][m - 1] != 0) {
            i32 mask = a[n - 1][m - 2] * 2 + a[n - 1][m - 1];
            print(mask, n - 2, m - 2);
        }
        std::cout << ans.size() / 3 << "\n";
        for (i32 i = 0; i < ans.size(); i += 3) {
            std::cout << ans[i].first + 1 << " " << ans[i].second + 1 << " ";
            std::cout << ans[i + 1].first + 1 << " " << ans[i + 1].second + 1 << " ";
            std::cout << ans[i + 2].first + 1 << " " << ans[i + 2].second + 1 << "\n";
        }
    }
    return 0;
}


#include <bits/stdc++.h>

template <typename T> inline void rd(T& x) {
	int si = 1; char c = getchar(); x = 0;
	while(!isdigit(c)) si = c == '-' ? -1 : si, c = getchar();
	while(isdigit(c)) x = x * 10 + c - 48, c = getchar();
	x *= si;
}
template <typename T, typename... Args>
inline void rd(T& x, Args&... args) { rd(x); rd(args...); }
#define fi first
#define se second
#define mkp std::make_pair
typedef long long ll;
typedef double ff;
typedef std::pair <int, int> pii;
const int kN = 1e3 + 5, kInf = 0x3f3f3f3f;
const ll kMod = 998244353, kInfLL = 0x3f3f3f3f3f3f3f3fLL;

int n, m, A[kN][kN], opt[kN * kN], cnt = 0; char str[kN][kN];
void Print(int a1, int a2, int a3, int a4, int a5, int a6) {
	opt[++cnt] = a1; opt[++cnt] = a2; opt[++cnt] = a3;
	opt[++cnt] = a4; opt[++cnt] = a5; opt[++cnt] = a6;
}
void Print(int a1, int a2) {
	opt[++cnt] = a1; opt[++cnt] = a2;
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
#endif
	int T = 1; rd(T);
	while(T--) {
		cnt = 0;
		rd(n, m);
		for(int i = 1; i <= n; ++i) {
			scanf("%s", str[i] + 1);
			for(int j = 1; j <= m; ++j)
				A[i][j] = (str[i][j] == '1');
		}
		if(n % 2 != 0) {
			for(int i = 1; i < m; ++i)
				if(A[n][i] == 1) {
					Print(n, i, n - 1, i + 1, n - 1, i);
					A[n][i] ^= 1; A[n - 1][i + 1] ^= 1; A[n - 1][i] ^= 1;
				}
			if(A[n][m] == 1) {
				Print(n, m, n - 1, m - 1, n - 1, m);
				A[n][m] ^= 1; A[n - 1][m - 1] ^= 1; A[n - 1][m] ^= 1;
			}
		}
		if(m % 2 != 0) {
			if(A[1][m] == 1) {
				Print(1, m, 1, m - 1, 2, m - 1);
				A[1][m] ^= 1; A[1][m - 1] ^= 1; A[2][m - 1] ^= 1;
			}
			for(int i = 2; i <= (n % 2 != 0 ? n - 1 : n); ++i)
				if(A[i][m] == 1) {
					Print(i, m, i, m - 1, i - 1, m - 1);
					A[i][m] ^= 1; A[i][m - 1] ^= 1; A[i - 1][m - 1] ^= 1;
				}
			//printf("?");
		}
		/*for(int i = 1; i <= n; ++i) {
			for(int j = 1; j <= m; ++j)
				printf("%d ", A[i][j]);
			printf("\n");
		}*/
		for(int i = 1; i <= n; i += 2) {
			for(int j = 1; j <= m; j += 2) {
				int s[2][2] = { { 0, 0 }, { 0, 0 } };
				for(int k1 = 0; k1 < 2; ++k1)
					for(int k2 = 0; k2 < 2; ++k2) {
						if(A[i + k1][j + k2]) {
							for(int p1 = 0; p1 < 2; ++p1)
								for(int p2 = 0; p2 < 2; ++p2)
									if(p1 != k1 || p2 != k2)
										s[p1][p2] ^= 1;
						}
					}
				for(int k1 = 0; k1 < 2; ++k1)
					for(int k2 = 0; k2 < 2; ++k2)
						if(s[k1][k2]) {
							for(int p1 = 0; p1 < 2; ++p1)
								for(int p2 = 0; p2 < 2; ++p2)
									if(p1 != k1 || p2 != k2) {
										Print(i + p1, j + p2);
									}
						}
			}
		}
		printf("%d\n", cnt / 6);
		for(int i = 1; i <= cnt; ++i) {
			printf("%d ", opt[i]);
			if(i % 6 == 0) printf("\n");
		}
	} return 0;
}


#include <bits/stdc++.h>

template <typename T> inline void rd(T& x) {
	int si = 1; char c = getchar(); x = 0;
	while(!isdigit(c)) si = c == '-' ? -1 : si, c = getchar();
	while(isdigit(c)) x = x * 10 + c - 48, c = getchar();
	x *= si;
}
template <typename T, typename... Args>
inline void rd(T& x, Args&... args) { rd(x); rd(args...); }
#define fi first
#define se second
#define mkp std::make_pair
typedef long long ll;
typedef double ff;
typedef std::pair <int, int> pii;
const int kN = 1e3 + 5, kInf = 0x3f3f3f3f;
const ll kMod = 998244353, kInfLL = 0x3f3f3f3f3f3f3f3fLL;

int n, m, A[kN][kN], opt[kN * kN], cnt = 0; char str[kN][kN];
void Print(int a1, int a2, int a3, int a4, int a5, int a6) {
	opt[++cnt] = a1; opt[++cnt] = a2; opt[++cnt] = a3;
	opt[++cnt] = a4; opt[++cnt] = a5; opt[++cnt] = a6;
}
void Print(int a1, int a2) {
	opt[++cnt] = a1; opt[++cnt] = a2;
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
#endif
	int T = 1; rd(T);
	while(T--) {
		cnt = 0;
		rd(n, m);
		for(int i = 1; i <= n; ++i) {
			scanf("%s", str[i] + 1);
			for(int j = 1; j <= m; ++j)
				A[i][j] = (str[i][j] == '1');
		}
		if(n % 2 != 0) {
			for(int i = 1; i < m; ++i)
				if(A[n][i] == 1) {
					Print(n, i, n - 1, i + 1, n - 1, i);
					A[n][i] ^= 1; A[n - 1][i + 1] ^= 1; A[n - 1][i] ^= 1;
				}
			if(A[n][m] == 1) {
				Print(n, m, n - 1, m - 1, n - 1, m);
				A[n][m] ^= 1; A[n - 1][m - 1] ^= 1; A[n - 1][m] ^= 1;
			}
		}
		if(m % 2 != 0) {
			if(A[1][m] == 1) {
				Print(1, m, 1, m - 1, 2, m - 1);
				A[1][m] ^= 1; A[1][m - 1] ^= 1; A[2][m - 1] ^= 1;
			}
			for(int i = 2; i <= (n % 2 != 0 ? n - 1 : n); ++i)
				if(A[i][m] == 1) {
					Print(i, m, i, m - 1, i - 1, m - 1);
					A[i][m] ^= 1; A[i][m - 1] ^= 1; A[i - 1][m - 1] ^= 1;
				}
			//printf("?");
		}
		/*for(int i = 1; i <= n; ++i) {
			for(int j = 1; j <= m; ++j)
				printf("%d ", A[i][j]);
			printf("\n");
		}*/
		for(int i = 1; i <= n - n % 2; i += 2) {
			for(int j = 1; j <= m - m % 2; j += 2) {
				int s[2][2] = { { 0, 0 }, { 0, 0 } };
				for(int k1 = 0; k1 < 2; ++k1)
					for(int k2 = 0; k2 < 2; ++k2) {
						if(A[i + k1][j + k2]) {
							for(int p1 = 0; p1 < 2; ++p1)
								for(int p2 = 0; p2 < 2; ++p2)
									if(p1 != k1 || p2 != k2)
										s[p1][p2] ^= 1;
						}
					}
				for(int k1 = 0; k1 < 2; ++k1)
					for(int k2 = 0; k2 < 2; ++k2)
						if(s[k1][k2]) {
							for(int p1 = 0; p1 < 2; ++p1)
								for(int p2 = 0; p2 < 2; ++p2)
									if(p1 != k1 || p2 != k2) {
										Print(i + p1, j + p2);
									}
						}
			}
		}
		printf("%d\n", cnt / 6);
		for(int i = 1; i <= cnt; ++i) {
			printf("%d ", opt[i]);
			if(i % 6 == 0) printf("\n");
		}
	} return 0;
}


#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
#define ll long long
const int N = 1<<20;
const int M = 1e5+5;
int n,m,len;ll a[N],b[N];char s[20][M];
void fwt(ll *P,int opt){
	for (int i=1;i<len;i<<=1)
		for (int p=i<<1,j=0;j<len;j+=p)
			for (int k=0;k<i;++k){
				ll x=P[j+k],y=P[j+k+i];
				P[j+k]=(x+y)/opt;P[j+k+i]=(x-y)/opt;
			}
}
int main(){
	n=gi();m=gi();len=1<<n;
	for (int i=0;i<n;++i) scanf("%s",s[i]+1);
	for (int i=1;i<=m;++i){
		int x=0;
		for (int j=0;j<n;++j) x=(x<<1)+s[j][i]-'0';
		++a[x];
	}
	for (int i=1;i<len;++i) b[i]=b[i>>1]+(i&1);
	for (int i=1;i<len;++i) b[i]=min(b[i],n-b[i]);
	fwt(a,1);fwt(b,1);
	for (int i=0;i<len;++i) a[i]*=b[i];
	fwt(a,2);
	ll ans=a[0];
	for (int i=1;i<len;++i) ans=min(ans,a[i]);
	printf("%I64d\n",ans);return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=112345;
const long long maxn=0x3f3f3f3f3f3f3f3fll;
void sol(long long a[],int n,bool on)
{
    for(int d=1;d<n;d<=1)
	{
        for(int k=d<<1,i=0;i<n;i+=k)
		{
            for(int j=0;j<d;j++)
			{
                long long x=a[i+j],y=a[i+j+d];
                if(on)
				{
                    a[i+j]=(x+y);
                    a[i+j+d]=(x-y);
                }
                else
				{
                    a[i+j]=(x+y)/2;
                    a[i+j+d]=(x-y)/2;
                }
            }
        }
    }
}
char sb[22][maxn];
int sa[maxn];
long long la[1<<22],lb[1<<22];
int getone(int x,int n)
{
    int ret=0;
    while(x)
	{
        ret+=x&1;
        x>>=1;
    }
    return min(ret,n-ret);
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
    	cin>>sb[i];
	}
    for(int i=0;i<m;i++)
	{
        sa[i]=0;
        for(int j=0;j<n;j++)
		{
            sa[i]|=(sb[j][i]-'0')<<j;
        }
    }
    memset(la,0,sizeof(la));
    for(int i=0;i<m;i++)
    {
		la[sa[i]]++;
	}
    for(int i=0;i<(1<<n);i++)
	{
        lb[i]=getone(i,n);
    }
    sol(la,1<<n,true);
    sol(lb,1<<n,true);
    for(int i=0;i<(1<<n);i++)
    {
		la[i]*=lb[i];
	}
    sol(la,1<<n,false);
    long long ans=maxn;
    for(int i=0;i<(1<<n);i++)
    {
		ans=min(ans,la[i]);
	}
    cout<<ans;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int maxn = 112345;
#define LL long long
const LL INFF = 0x3f3f3f3f3f3f3f3fll;

void fwt (LL a[] , int n ,bool on) {
    for ( int d = 1 ; d < n ; d <<= 1 ) {
        for ( int k = d << 1 , i = 0 ; i < n ; i += k ) {
            for ( int j = 0 ; j < d ; ++ j ) {
                LL x = a[i + j] , y = a[i + j + d] ;
                if(on){
                    a[i + j] = ( x + y )  ;
                    a[i + j + d] = ( x - y  )  ;
                }
                else{
                    a[i + j] = ( x + y ) / 2 ;
                    a[i + j + d] = ( x - y ) / 2;
                }
            }
        }
    }
}

char inp[22][maxn];
int arr[maxn];
LL A[1<<22],B[1<<22];

int getone(int x,int n){
    int ret = 0 ;
    while(x){
        ret += x & 1;
        x >>= 1;
    }
    return min(ret,n - ret);
}

int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i = 0 ; i < n; i ++) scanf("%s",inp[i]);
    for(int i = 0 ; i < m ; i++){
        arr[i] = 0;
        for(int j = 0 ; j < n ; j ++){
            arr[i] |= (inp[j][i] - '0') << j;
        }
    }
    memset(A,0,sizeof(A));
    for(int i = 0 ; i < m ; i++) A[arr[i]] ++;
    for(int i = 0 ; i < (1<<n) ; i ++){
        B[i] = getone(i,n);
    }
    fwt(A,1<<n,true);
    fwt(B,1<<n,true);
    for(int i = 0; i < (1<<n);i++) A[i] *= B[i];
    fwt(A,1<<n,false);
    LL ans = INFF;
    for(int i = 0 ; i < (1<<n);i++) ans = min(ans,A[i]);
    printf("%I64d\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long llu;
const int maxn=1e6+10;
const int mod=1000000007;
ll t,n,k,m,tot;
struct node
{
	int x1,y1;
	int x2,y2;
	int x3,y3;
	node(){}
	node(int a,int b,int c,int d,int e,int f)
	{
		x1=a,y1=b;
    	x2=c,y2=d;
    	x3=e,y3=f;
	}
};
char a[110][110];
int main( )
{
//	ios::sync_with_stdio(false);
	cin>>t;
	while(t--)
	{
		vector<node>v;
		cin>>n>>m;
		for(int i=1;i<=n;i++)
		    scanf("%s",a[i]+1);
		for(int i=1;i<=n-1;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(a[i][j]=='1')
				{
					if(j==1)
					{
						v.push_back(node(i,j,i,j+1,i+1,j));
						v.push_back(node(i,j,i,j+1,i+1,j+1));
						v.push_back(node(i,j,i+1,j,i+1,j+1));
					}
					else if(j==m)
					{
						v.push_back(node(i,j,i,j-1,i+1,j));
						v.push_back(node(i,j,i,j-1,i+1,j-1));
						v.push_back(node(i,j,i+1,j,i+1,j-1));
					}
					else
					{
						v.push_back(node(i,j,i,j+1,i+1,j));
						v.push_back(node(i,j,i,j+1,i+1,j+1));
						v.push_back(node(i,j,i+1,j,i+1,j+1));
					}
				}
			}
		}
		for(int i=1;i<=m;i++)
		{
			if(a[n][i]=='1')
			{
				if(i<m)
				{
					v.push_back(node(n-1,i,n,i,n,i+1));
					v.push_back(node(n-1,i+1,n,i,n,i+1));
					v.push_back(node(n-1,i,n-1,i+1,n,i));
				}
				else if(i==m)
				{
					v.push_back(node(n-1,i,n,i,n,i-1));
					v.push_back(node(n-1,i-1,n,i,n,i-1));
					v.push_back(node(n-1,i-1,n-1,i,n,i));
				}
			}
		}
		cout<<v.size()<<endl;
		for(int i=0;i<v.size();i++)
		{
			cout<<v[i].x1<<' '<<v[i].y1<<' '<<v[i].x2<<' '<<v[i].y2<<' '<<v[i].x3<<' '<<v[i].y3<<endl;
		}
	}
    return 0;
}


/*

*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<cstdlib>
#include<stack>
using namespace std;
#define ll long long
#define N 103
#define INF 0x3f3f3f3f
#define FOR(i, st, en) for(i=st; i<en; i++)
#define printD(n) printf("%d", n)
#define printS(s) printf("%s", s)
#define readD(n) scanf("%d", &n)
#define readS(s) scnaf("%s", &s)
#define lson rt<<1, l, mid
#define rson (rt<<1)|1, mid+1, r
#define max(a, b) ((a)>(b)?(a):(b))
#define min(a, b) ((a)<(b)?(a):(b))
#define mkp make_pair
template <typename T> inline void read(T &x){char c; bool nega=0; while((!isdigit(c=getchar()))&&(c!='-')); if(c=='-'){nega=1; c=getchar();} x=c-48; while(isdigit(c=getchar())) x=x*10+c-48; if(nega) x=-x;}
template <typename T> inline void writep(T x){if(x>9) writep(x/10); putchar(x%10+48);}
template <typename T> inline void write(T x){if(x<0){ putchar('-'); x=-x;} writep(x);}
template <typename T> inline void writeln(T x){write(x); putchar('\n');}
//#define _DEBUG_
int n, m, a[N][N], cnt;
string b[N];

struct node{
	int xy[6];
	node(int a0=0, int a1=0, int a2=0, int a3=0, int a4=0, int a5=0){
		xy[0] = a0, xy[1] = a1,xy[2] = a2,xy[3] = a3,xy[4] = a4,xy[5] = a5;
	}
	void print(){
		for(int i=0; i<6; i++)
			cout<<xy[i]+1<<' ';
		cout<<endl;
	}
}ret[20003];

void change(int i, int j){
	int a11 = a[i][j], a12=a[i][j+1], a21 = a[i+1][j], a22 = a[i+1][j+1];
	if(a11==1){
		if(a12==1){
			if(a21 ==1 ){
				ret[cnt++] = node(i, j, i, j+1, i+1, j);
				a[i][j] = !a[i][j], a[i][j+1] = !a[i][j+1],a[i+1][j] = !a[i+1][j];
			}
			else{
				ret[cnt++]=node(i, j, i, j+1, i+1, j+1);
				a[i][j] = !a[i][j], a[i][j+1] = !a[i][j+1],a[i+1][j+1] = !a[i+1][j+1];
			}

		} else{
			ret[cnt++]=node(i, j, i+1, j, i+1, j+1);
			a[i][j] = !a[i][j], a[i+1][j] = !a[i+1][j],a[i+1][j+1] = !a[i+1][j+1];
		}

	}
	a12=a[i][j+1];
	if(j==m-2 && a12==1){
		ret[cnt++] = node(i, j+1, i+1, j, i+1, j+1);
		a[i][j+1] = !a[i][j+1], a[i+1][j] = !a[i+1][j],a[i+1][j+1] = !a[i+1][j+1];
	}

}

int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int i, j, t;

	#ifdef _DEBUG_
	freopen("A1 Binary Table (Easy Version).in", "r", stdin);
	//freopen(".out", "w", stdout);
	#endif
	cin>>t;
	while(t--){
		cin>>n>>m;
		for(i=0; i<n; i++)
			cin>>b[i];
		for(i=0; i<n; i++)
			for(j=0; j<m; j++)
				a[i][j] = b[i][j] - '0';
		cnt = 0;
		for(i=0; i<n-1; i++)
			for(j=0; j<m-1; j++){
				change(i, j);
			}
		for(j=0; j<m-1; j++){
			int a1 = a[n-1][j], a2 = a[n-1][j+1];
			if(a1==1 && a2==1){
				ret[cnt++] = node(n-2, j, n-2, j+1, n-1, j);
				ret[cnt++] = node(n-2, j, n-2, j+1, n-1, j+1);
				a[n-1][j]=0, a[n-1][j+1]=0;
			} else if(a1==1){
				ret[cnt++] = node(n-2, j, n-2, j+1, n-1, j);
				ret[cnt++] = node(n-2, j, n-1, j, n-1, j+1);
				ret[cnt++] = node(n-2, j+1, n-1, j, n-1, j+1);
				a[n-1][j]=0, a[n-1][j+1]=0;
			}
			a2 = a[n-1][j+1];
			if(j==m-2 && a2==1){
				ret[cnt++] = node(n-2, j, n-2, j+1, n-1, j+1);
				ret[cnt++] = node(n-2, j, n-1, j, n-1, j+1);
				ret[cnt++] = node(n-2, j+1, n-1, j, n-1, j+1);
				a[n-1][j]=0, a[n-1][j+1]=0;
			}
		}

		cout<<cnt<<endl;
		for(i=0; i<cnt; i++)
			ret[i].print();
	}
	return 0;
}


/*

*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<cstdlib>
#include<stack>
using namespace std;
#define ll long long
#define N 103
#define INF 0x3f3f3f3f
#define FOR(i, st, en) for(i=st; i<en; i++)
#define printD(n) printf("%d", n)
#define printS(s) printf("%s", s)
#define readD(n) scanf("%d", &n)
#define readS(s) scnaf("%s", &s)
#define lson rt<<1, l, mid
#define rson (rt<<1)|1, mid+1, r
#define max(a, b) ((a)>(b)?(a):(b))
#define min(a, b) ((a)<(b)?(a):(b))
#define mkp make_pair
template <typename T> inline void read(T &x){char c; bool nega=0; while((!isdigit(c=getchar()))&&(c!='-')); if(c=='-'){nega=1; c=getchar();} x=c-48; while(isdigit(c=getchar())) x=x*10+c-48; if(nega) x=-x;}
template <typename T> inline void writep(T x){if(x>9) writep(x/10); putchar(x%10+48);}
template <typename T> inline void write(T x){if(x<0){ putchar('-'); x=-x;} writep(x);}
template <typename T> inline void writeln(T x){write(x); putchar('\n');}
//#define _DEBUG_
int n, m, a[N][N], cnt;
string b[N];

struct node{
	int xy[6];
	node(int a0=0, int a1=0, int a2=0, int a3=0, int a4=0, int a5=0){
		xy[0] = a0, xy[1] = a1,xy[2] = a2,xy[3] = a3,xy[4] = a4,xy[5] = a5;
	}
	void print(){
		for(int i=0; i<6; i++)
			cout<<xy[i]+1<<' ';
		cout<<endl;
	}
}ret[20003];

void change(int i, int j){
	int a11 = a[i][j], a12=a[i][j+1], a21 = a[i+1][j], a22 = a[i+1][j+1];
	if(a11==1){
		if(a12==1){
			if(a21 ==1 ){
				ret[cnt++] = node(i, j, i, j+1, i+1, j);
				a[i][j] = !a[i][j], a[i][j+1] = !a[i][j+1],a[i+1][j] = !a[i+1][j];
			}
			else{
				ret[cnt++]=node(i, j, i, j+1, i+1, j+1);
				a[i][j] = !a[i][j], a[i][j+1] = !a[i][j+1],a[i+1][j+1] = !a[i+1][j+1];
			}

		} else{
			ret[cnt++]=node(i, j, i+1, j, i+1, j+1);
			a[i][j] = !a[i][j], a[i+1][j] = !a[i+1][j],a[i+1][j+1] = !a[i+1][j+1];
		}

	}
	if(j==m-2 && a12==1){
		ret[cnt++] = node(i, j+1, i+1, j, i+1, j+1);
		a[i][j+1] = !a[i][j+1], a[i+1][j] = !a[i+1][j],a[i+1][j+1] = !a[i+1][j+1];
	}

}

int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int i, j, t;

	#ifdef _DEBUG_
	freopen("A1 Binary Table (Easy Version).in", "r", stdin);
	//freopen(".out", "w", stdout);
	#endif
	cin>>t;
	while(t--){
		cin>>n>>m;
		for(i=0; i<n; i++)
			cin>>b[i];
		for(i=0; i<n; i++)
			for(j=0; j<m; j++)
				a[i][j] = b[i][j] - '0';
		cnt = 0;
		for(i=0; i<n-1; i++)
			for(j=0; j<m-1; j++){
				change(i, j);
			}
		for(j=0; j<m-1; j++){
			int a1 = a[n-1][j], a2 = a[n-1][j+1];
			if(a1==1 && a2==1){
				ret[cnt++] = node(n-2, j, n-2, j+1, n-1, j);
				ret[cnt++] = node(n-2, j, n-2, j+1, n-1, j+1);
				a[n-1][j]=0, a[n-1][j+1]=0;
			} else if(a1==1){
				ret[cnt++] = node(n-2, j, n-2, j+1, n-1, j);
				ret[cnt++] = node(n-2, j, n-1, j, n-1, j+1);
				ret[cnt++] = node(n-2, j+1, n-1, j, n-1, j+1);
				a[n-1][j]=0, a[n-1][j+1]=0;
			}
			if(j==m-2 && a2==1){
				ret[cnt++] = node(n-2, j, n-2, j+1, n-1, j+1);
				ret[cnt++] = node(n-2, j, n-1, j, n-1, j+1);
				ret[cnt++] = node(n-2, j+1, n-1, j, n-1, j+1);
				a[n-1][j]=0, a[n-1][j+1]=0;
			}
		}

		cout<<cnt<<endl;
		for(i=0; i<cnt; i++)
			ret[i].print();
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define mod 1000000007
#define mod2 998244353
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define vi vector<ll>
#define pb push_back
#define ld long double
#define vpi vector<pair<ll,ll>>
#define vvi vector<vector<ll>>

#define debug(a) { cout << #a << " = " << a << endl;}

void sep(string SS = "BLOCK") {
    cout << "-------------" << SS << "-----------------\n";
}

template<typename T>
void debugv(vector<T> arr) {
    for (auto t: arr)
        cout << t << " ";
    cout << "\n";
}

template<typename T>
void debugarr(T arr, int n) {
    for (int i=0;i<n;i++) cout << arr[i] << " ";
    cout << "\n";
}

template<typename T>
void chmax(T& a, T b) {
    if (a < b)
        a = b;
}

template<typename T>
void chmin(T& a, T b) {
    if (a > b)
        a = b;
}

ll min(ll a, ll b) {
    return a < b ? a : b;
}

ll max(ll a, ll b) {
    return a > b ? a : b;
}

const int maxn = 4e2+100;
const ll INF = 1e18;
ll arr[maxn][maxn], n, m, t, k, q;
unordered_map<ll,ll> u;
string s;

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    cin>>t;
    while (t--) {
        cin>>n>>m;
        for (ll i=0;i<n;i++) {
            cin>>s;
            for (ll j=0;j<m;j++) {
                arr[i][j] = s[j] == '1' ? 1 : 0;
            }
        }
        vvi ops;

        for (ll i=n-1;i>=2;i--) {
            for (ll j=0;j<m;j++) {
                if (arr[i][j]) {
                    ops.pb({i,j,i-1,j,i-1,(j?j-1:j+1)});
                    arr[i][j] ^= 1;
                    arr[i-1][j] ^= 1;
                    arr[i-1][j?j-1:j+1] ^= 1;
                }
            }
        }

        for (ll j=m-1;j>=2;j--) {
            if (arr[1][j] && arr[0][j]) {
                ops.pb({1,j,0,j,0,j-1});
                arr[1][j] ^= 1;
                arr[0][j] ^= 1;
                arr[0][j-1] ^= 1;
            } else if (arr[1][j]) {
                ops.pb({1,j,1,j-1,0,j-1});
                arr[1][j] ^= 1;
                arr[1][j-1] ^= 1;
                arr[0][j-1] ^= 1;
            } else if (arr[0][j]) {
                ops.pb({0,j,0,j-1,1,j-1});
                arr[0][j] ^= 1;
                arr[0][j-1] ^= 1;
                arr[1][j-1] ^= 1;
            }
        }

        if (arr[0][0] ^ arr[0][1] ^ arr[1][0])
            ops.pb({0,0,0,1,1,0});
        if (arr[0][0] ^ arr[0][1] ^ arr[1][1])
            ops.pb({0,0,0,1,1,1});
        if (arr[0][0] ^ arr[1][0] ^ arr[1][1])
            ops.pb({0,0,1,0,1,1});
        if (arr[0][1] ^ arr[1][0] ^ arr[1][1])
            ops.pb({0,1,1,0,1,1});

        cout << ops.size() << endl;
        for (vi op: ops) {
            for (ll i=0;i<6;i++) {
                cout << op[i] + 1 << " ";
            }
            cout << endl;
        }
    }
}


#define DEBUG

#include <bits/stdc++.h>

using namespace std;

char mpp[110][110];
int mp[110][110];

struct node {
    int x1, y1, x2, y2, x3, y3;

    node(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0, int x3 = 0, int y3 = 0) : x1(x1), y1(y1), x2(x2), y2(y2),
                                                                                x3(x3), y3(y3) {}
};

node ans[110 * 110];
int cnt;

void change(int x1, int y1, int x2, int y2, int x3, int y3) {
    ans[cnt++] = node(x1, y1, x2, y2, x3, y3);
    mp[x1][y1] ^= 1, mp[x2][y2] ^= 1, mp[x3][y3] ^= 1;
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n, m;
        cin >> n >> m;
        for (int i = 0; i < n; i++) {
            scanf("%s", mpp[i]);
            for (int j = 0; j < m; j++) mp[i][j] = mpp[i][j] - '0';
        }
        cnt = 0;
        for (int i = 0; i < n - 2; ++i) {
            for (int j = 0; j < n - 1; ++j) {
                if (mp[i][j]) {
                    change(i, j, i, j + 1, i + 1, j + 1);
                }
            }
            if (mp[i][n - 1]) {
                change(i, n - 1, i + 1, n - 1, i + 1, n - 2);
            }
        }
        int i = n - 2;
        for (int j = 0; j < n - 2; j++) {
            if (mp[i][j]) {
                change(i, j, i, j + 1, i + 1, j + 1);
            }
            if (mp[i + 1][j]) {
                change(i, j, i, j + 1, i - 1, j + 1);
            }
        }
        int j = n - 1;
        int tmp = mp[i][i] + mp[j][j] + mp[i][j] + mp[j][i];
        if (tmp == 4) {
            change(i, j, j, i, j, j);
            change(i, i, j, i, j, j);
            change(i, i, i, j, j, j);
            change(i, i, i, j, j, i);
        } else if (tmp == 3) {
            if (mp[i][i] == 0) change(i, j, j, i, j, j);
            else if (!mp[i][j]) change(i, i, j, i, j, j);
            else if (!mp[j][i]) change(i, i, i, j, j, j);
            else change(i, i, i, j, j, i);
        } else if (tmp == 2) {
            if (mp[i][i] == 1 && mp[i][j]) change(i, j, j, i, j, j), change(i, i, j, i, j, j);
            else if (mp[i][i] && mp[j][i]) change(i, j, j, i, j, j), change(i, i, i, j, j, j);
            else if (mp[i][j] && mp[j][j]) change(i, i, j, i, j, j), change(i, i, i, j, j, i);
            else if (mp[j][i] && mp[j][j]) change(i, i, i, j, j, i), change(i, i, i, j, j, j);
        } else if (tmp == 1) {
            if (mp[i][i] == 1) change(i, i, j, i, j, j), change(i, i, i, j, j, i), change(i, i, i, j, j, j);
            else if (mp[i][j]) change(i, j, j, i, j, j), change(i, i, i, j, j, i), change(i, i, i, j, j, j);
            else if (mp[j][i]) change(i, i, i, j, j, i), change(i, j, j, i, j, j), change(i, i, j, i, j, j);
            else if (mp[j][j]) change(i, i, i, j, j, j), change(i, j, j, i, j, j), change(i, i, j, i, j, j);
        }
        printf("%d\n", cnt);
        for (int k = 0; k < cnt; ++k) {
            node &x = ans[k];
            printf("%d %d %d %d %d %d\n", x.x1, x.y1, x.x2, x.y2, x.x3, x.y3);
        }
#ifdef DEBUG
        cout << flush;
#endif
    }
    return 0;
}


#define DEBUG

#include <bits/stdc++.h>

using namespace std;

char mpp[110][110];
int mp[110][110];

struct node {
    int x1, y1, x2, y2, x3, y3;

    node(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0, int x3 = 0, int y3 = 0) : x1(x1), y1(y1), x2(x2), y2(y2),
                                                                                x3(x3), y3(y3) {}
};

node ans[110 * 110];
int cnt;

void change(int x1, int y1, int x2, int y2, int x3, int y3) {
    ans[cnt++] = node(x1, y1, x2, y2, x3, y3);
    mp[x1][y1] ^= 1, mp[x2][y2] ^= 1, mp[x3][y3] ^= 1;
}

void debug(int n, int m) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            printf("%d ", mp[i][j]);
        }
        cout << endl;
    }
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; i++) {
            scanf("%s", mpp[i] + 1);
            for (int j = 1; j <= m; j++) mp[i][j] = mpp[i][j] - '0';
        }
        cnt = 0;
        for (int i = 1; i <= n - 2; ++i) {
            for (int j = 1; j <= m - 1; ++j) {
                if (mp[i][j]) {
                    change(i, j, i, j + 1, i + 1, j + 1);
//                    debug(n, m);
                }

            }
            if (mp[i][m]) {
                change(i, m, i + 1, m, i + 1, m - 1);
//                debug(n, m);
            }
        }
        int i = n - 1;
        for (int j = 1; j <= m - 2; j++) {
            if (mp[i][j]) {
                change(i, j, i, j + 1, i + 1, j + 1);
//                debug(n, m);
            }
            if (mp[i + 1][j]) {
                change(i + 1, j, i + 1, j + 1, i, j + 1);
//                debug(n, m);
            }
        }
        int j = m - 1;
        int tmp = mp[i][j] + mp[n][m] + mp[i][m] + mp[n][j];
#define c1 change(i, m, n, j, n, m)
#define c2 change(i, j, n, j, n, m)
#define c3 change(i, j, i, m, n, m)
#define c4 change(i, j, i, m, n, j)
        if (tmp == 4) {
            c1, c2, c3, c4;
        } else if (tmp == 3) {
            if (mp[i][j] == 0) c1;
            else if (!mp[i][m]) c2;
            else if (!mp[n][j]) c3;
            else if (!mp[n][m]) c4;
        } else if (tmp == 2) {
            if (mp[i][j] == 1 && mp[i][m]) c1, c2;
            else if (mp[i][j] && mp[n][j]) c1, c3;
            else if (mp[i][m] && mp[n][m]) c2, c4;
            else if (mp[n][j] && mp[n][m]) c3, c4;
            else if (mp[i][j] && mp[n][m]) c1, c4;
            else if (mp[i][m] && mp[n][j]) c2, c3;
        } else if (tmp == 1) {
            if (mp[i][j] == 1) c2, c3, c4;
            else if (mp[i][m]) c1, c3, c4;
            else if (mp[n][j]) c4, c1, c2;
            else if (mp[n][m]) c3, c1, c2;
        }
        printf("%d\n", cnt);
        for (int k = 0; k < cnt; ++k) {
            node &x = ans[k];
            printf("%d %d %d %d %d %d\n", x.x1, x.y1, x.x2, x.y2, x.x3, x.y3);
        }
#ifdef DEBUG
        cout << flush;
#endif
    }
    return 0;
}


//khodaya khodet komak kon
# include <bits/stdc++.h>

/*
// ordered_set
# include <ext/pb_ds/assoc_container.hpp>
# include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
# define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
*/

using namespace std;

typedef long long                                        ll;
typedef long double                                      ld;
typedef pair <int, int>                                  pii;
typedef pair <pii, int>                                  ppi;
typedef pair <int, pii>                                  pip;
typedef pair <pii, pii>                                  ppp;
typedef pair <ll, ll>                                    pll;

# define A                                               first
# define B                                               second
# define endl                                            '\n'
# define sep                                             ' '
# define all(x)                                          x.begin(), x.end()
# define kill(x)                                         return cout << x << endl, 0
# define SZ(x)                                           int(x.size())
# define lc                                              id << 1
# define rc                                              id << 1 | 1
# define InTheNameOfGod                                  ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);

ll power(ll a, ll b, ll md) {return (!b ? 1 : (b & 1 ? a * power(a * a % md, b / 2, md) % md : power(a * a % md, b / 2, md) % md));}

const int xn = 1e3 + 10;
const int xm = - 20 + 10;
const int sq = 320;
const int inf = 1e9 + 10;
const ll INF = 1e18 + 10;
const int mod = 998244353;
const int base = 257;

int qq, n, m, a[xn][xn], ans[6][xn * xn], ptr;
string s;

void add(int x1, int y1, int x2, int y2, int x3, int y3){
	ans[0][ptr] = x1;
	ans[1][ptr] = y1;
	ans[2][ptr] = x2;
	ans[3][ptr] = y2;
	ans[4][ptr] = x3;
	ans[5][ptr] = y3;
	a[x1][y1] ^= 1;
	a[x2][y2] ^= 1;
	a[x3][y3] ^= 1;
	++ ptr;
}

int main(){
	//InTheNameOfGod;

	cin >> qq;
	while (qq --){
		cin >> n >> m;
		for (int i = 1; i <= n; ++ i){
			cin >> s;
			for (int j = 1; j <= m; ++ j)
				a[i][j] = s[j - 1] - '0';
		}
		ptr = 0;
		if (n % 2 || m % 2){
			if (a[n][m])
				add(n, m, n - 1, m, n, m - 1);
			if (n % 2){
				for (int i = 1; i < m; ++ i){
					if (a[n][i]){
						if (i < m - 1)
							add(n, i, n - 1, i, n - 1, i + 1);
						else
							add(n, i, n - 1, i, n - 1, i - 1);
					}
				}
			}
			if (m % 2){
				for (int i = 1; i < n; ++ i){
					if (a[i][m]){
						if (i < n - 1)
							add(i, m, i, m - 1, i + 1, m - 1);
						else
							add(i, m, i, m - 1, i - 1, m - 1);
					}
				}
			}
		}
		for (int i = 1; i <= n - n % 2; i += 2){
			for (int j = 1; j <= m - m % 2; j += 2){
				//cout << i << " : " << j << endl;
				while (true){
					int ted = a[i][j] + a[i + 1][j] + a[i][j + 1] + a[i + 1][j + 1];
					//cout << ted << endl;
					if (!ted)
						break;
					if (ted == 4){
						add(i, j, i + 1, j, i, j + 1);
						continue;
					}
					vector <pii> vec[2];
					if (a[i][j])
						vec[1].push_back({i, j});
					else
						vec[0].push_back({i, j});
					if (a[i + 1][j])
						vec[1].push_back({i + 1, j});
					else
						vec[0].push_back({i + 1, j});
					if (a[i][j + 1])
						vec[1].push_back({i, j + 1});
					else
						vec[0].push_back({i, j + 1});
					if (a[i + 1][j + 1])
						vec[1].push_back({i + 1, j + 1});
					else
						vec[0].push_back({i + 1, j + 1});
					if (ted < 3)
						add(vec[1][0].A, vec[1][0].B, vec[0][0].A, vec[0][0].B, vec[0][1].A, vec[0][1].B);
					else
						add(vec[1][0].A, vec[1][0].B, vec[1][1].A, vec[1][1].B, vec[1][2].A, vec[1][2].B);
				}
			}
		}
		cout << ptr << endl;
		for (int i = 0; i < ptr; ++ i){
			for (int j = 0; j < 6; ++ j)
				cout << ans[j][i] << sep;
			cout << endl;
		}
	}

	return 0;
}