#define _USE_MATH_DEFINES
#include <algorithm>
#include <cstdio>
#include <functional>
#include <iostream>
#include <cfloat>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <vector>
#include <random>
#include <cassert>
using namespace std;

#define rep(i, N) for (int i = 0; i < N; i++)
#define pb push_back

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> i_i;
typedef pair<ll, int> ll_i;
typedef pair<int, ll> i_ll;
typedef pair<double, int> d_i;
typedef pair<ll, ll> ll_ll;
typedef pair<double, double> d_d;
struct edge { int v; ll w; };

const int MOD = 1000000007;
ll _MOD = 1000000009;
double EPS = 1e-10;
int INF = INT_MAX / 2;

struct bit {
	vector<int> a;
	bit(int N = 0) : a(N + 1) {}
	int get(int i) {
		int val = 0;
		for (; i; i -= i & -i) val = max(val, a[i]);
		return val;
	}
	void set(int i, int val) {
		for (i++; i < a.size(); i += i & -i) a[i] = max(a[i], val);
	}
};

struct segtree {
	segtree *lch, *rch;
	int N, val;
	segtree(int _N) : N(_N), val(0) {
		if (N > 1) {
			int n = N / 2;
			lch = new segtree(n);
			rch = new segtree(N - n);
		}
	}
	~segtree() {
		if (N > 1) { delete lch; delete rch; }
	}
	int get(int l, int r) {
		if (r <= 0 || N <= l) return 0;
		if (l <= 0 && N <= r) return val;
		int n = N / 2;
		return max(lch->get(l, r), rch->get(l - n, r - n));
	}
	void set(int i, int _val) {
		if (N == 1) {
			val = max(val, _val);
			return;
		}
		int n = N / 2;
		if (i < n) lch->set(i, _val);
		else rch->set(i - n, _val);
		val = max(lch->val, rch->val);
	}
};

struct segtree_2d {
	segtree_2d *lch, *rch;
	int H;
	vector<int> X;
	bit bt;
	segtree_2d(int _H, vector<int>& y, vector<int>& x) : H(_H) {
		if (H > 1) {
			int h = H / 2, N = y.size();
			vector<int> y1, x1, y2, x2;
			rep(i, N)
				if (y[i] < h) y1.pb(y[i]), x1.pb(x[i]);
				else y2.pb(y[i] - h), x2.pb(x[i]);
			lch = new segtree_2d(h, y1, x1);
			rch = new segtree_2d(H - h, y2, x2);
		}
		X = x;
		sort(X.begin(), X.end());
		X.erase(unique(X.begin(), X.end()), X.end());
		bt = bit(X.size()); // new segtree(X.size());
	}
	~segtree_2d() {
		if (H > 1) { delete lch; delete rch; }
	}
	int get(int yl, int yr, int xl, int xr) {
		if (yr <= 0 || H <= yl) return 0;
		if (yl <= 0 && H <= yr) {
			int l = lower_bound(X.begin(), X.end(), xl) - X.begin();
			int r = lower_bound(X.begin(), X.end(), xr) - X.begin();
			return bt.get(r);
		}
		int h = H / 2;
		return max(lch->get(yl, yr, xl, xr), rch->get(yl - h, yr - h, xl, xr));
	}
	void set(int y, int x, int _val) {
		if (H > 1) {
			int h = H / 2;
			if (y < h) lch->set(y, x, _val);
			else rch->set(y - h, x, _val);
		}
		int i = lower_bound(X.begin(), X.end(), x) - X.begin();
		bt.set(i, _val);
	}
};

int a, b, C = ~(1<<31), M = (1<<16)-1;
int r() {
	a = 36969 * (a & M) + (a >> 16);
	b = 18000 * (b & M) + (b >> 16);
	return (C & ((a << 16) + b)) % 1000000;
}

int compress(vector<int>& a) {
	vector<int> A = a;
	sort(A.begin(), A.end());
	A.erase(unique(A.begin(), A.end()), A.end());
	for (int& x: a) x = lower_bound(A.begin(), A.end(), x) - A.begin();
	return A.size();
}

struct dice {
	mt19937 mt;
	dice() {
		random_device rd;
		mt = mt19937(rd());
	}
	int operator()(int x) { return this->operator()(0, x - 1); }
	int operator()(int x, int y) {
		uniform_int_distribution<int> dist(x, y);
		return dist(mt);
	}
} dc;

int main() {
	/*
	for (;;) {
		cout << 'a' << endl;
		int N = 10000;
		vector<int> y(N), x(N), w(N);
		rep(i, N) y[i] = dc(100), x[i] = dc(100), w[i] = dc(100);
		segtree_2d* st = new segtree_2d(10000, y, x);
		rep(i, N) st->set(y[i], x[i], w[i]);
		rep(i, N) {
			int ans1 = st->get(0, y[i], 0, x[i]);
			int ans2 = 0;
			rep(j, N) if (y[j] < y[i] && x[j] < x[i])
				ans2 = max(ans2, w[j]);
			if (ans1 != ans2) cout << "ERR" << endl;
		}
	}
	*/
	for (;;) {
		int M, N, A, B;
		M = 0;
		N = 300000;
		A = dc(1, 1<<16);
		B = dc(1, 1<<16);
		scanf("%d%d%d%d", &M, &N, &A, &B);
		if (!(M + N)) break;
		vector<int> x(M + N), y(M + N), z(M + N);
		rep(i, M) scanf("%d%d%d", &x[i], &y[i], &z[i]);
		a = A; b = B;
		rep(i, N) x[M + i] = r(), y[M + i] = r(), z[M + i] = r();
		N = M + N;
		int W = compress(x), H = compress(y), D = compress(z);
		segtree_2d* st = new segtree_2d(H, y, x);
		vector<vector<int> > v(D);
		rep(i, N) v[z[i]].pb(i);
		vector<int> len(N);
		rep(z, D) {
			for (int i: v[z]) len[i] = st->get(0, y[i], 0, x[i]) + 1;
			for (int i: v[z]) st->set(y[i], x[i], len[i]);
		}
		delete st;
		int ans = 0;
		rep(i, N) ans = max(ans, len[i]);
		printf("%d\n", ans);
	}
}

Measured memory_bytes: 129884