Problem:
Problem G: Longest Chain

Let us compare two triples a = (xa, ya, za) and b = (xb, yb, zb) by a partial order ∠ defined as follows.

a ∠ b ⇔ xa < xb and ya < yb and za < zb

Your mission is to find, in the given set of triples, the longest ascending series a1 ∠ a2 ∠ ... ∠ ak.

Input

The input is a sequence of datasets, each specifying a set of triples formatted as follows.

m n A B
x1 y1 z1
x2 y2 z2
...
xm ym zm

Here, m, n, A and B in the first line, and all of xi, yi and zi (i = 1, . . . , m) in the following lines are non-negative integers.

Each dataset specifies a set of m + n triples. The triples p1 through pm are explicitly specified in the dataset, the i-th triple pi being (xi, yi, zi). The remaining n triples are specified by parameters A and B given to the following generator routine.

int a = A, b = 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;
}

Repeated 3n calls of r() defined as above yield values of xm+1, ym+1, zm+1, xm+2, ym+2, zm+2, ..., xm+n, ym+n, and zm+n, in this order.

You can assume that 1 ≤ m + n ≤ 3 × 105, 1 ≤ A,B ≤ 216, and 0 ≤ xk, yk, zk < 106 for 1 ≤ k ≤ m + n.

The input ends with a line containing four zeros. The total of m + n for all the datasets does not exceed 2 × 106.

Output

For each dataset, output the length of the longest ascending series of triples in the specified set. If pi1 ∠ pi2 ∠ ... ∠ pik is the longest, the answer should be k.

Sample Input

6 0 1 1
0 0 0
0 2 2
1 1 1
2 0 2
2 2 0
2 2 2
5 0 1 1
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
10 0 1 1
3 0 0
2 1 0
2 0 1
1 2 0
1 1 1
1 0 2
0 3 0
0 2 1
0 1 2
0 0 3
0 10 1 1
0 0 0 0

Output for the Sample Input

3
5
1
3

Solution in C++11 (judge verdict: Accepted)

#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <climits>
#include <iomanip>
#include <algorithm>
#include <queue>
#include <map>
#include <tuple>
#include <iostream>
#include <deque>
#include <array>
#include <set>
#include <functional>
#include <memory>
#include <stack>

struct Point3 {
	int x, y, z;
};
struct Point2 {
	int x, y;
	bool operator<(const Point2 other) const { return x < other.x; }
};
class NonChainablePoints {
	std::set<Point2> set;
public:
	NonChainablePoints() {};
	bool can_chain(const Point2& point) const {
		auto hint = set.lower_bound(point);
		return hint != set.begin() && (--hint)->y < point.y;
	}
	void insert(const Point2& point) {
		auto hint = set.lower_bound(point);
		if (hint == set.end() || hint->x != point.x || hint->y >= point.y) {
			while (hint != set.end() && hint->y >= point.y) hint = set.erase(hint);
			set.insert(point);
		}
	}
	bool is_empty() const { return set.empty(); }
	bool is_not_empty() const { return !is_empty(); }
};
int r(int& a, int& b) {
	constexpr int C = ~(1 << 31);
	constexpr int M = (1 << 16) - 1;
	a = 36969 * (a & M) + (a >> 16);
	b = 18000 * (b & M) + (b >> 16);
	return (C & ((a << 16) + b)) % 1000000;
}
void append_points(std::vector<Point3>& points, int a, int b, const int n) {
	for (auto i = 0; i < n; ++i) {
		Point3 p;
		p.x = r(a, b);
		p.y = r(a, b);
		p.z = r(a, b);
		points.push_back(p);
	}
}
int solve(const int m, const int n, const int a, const int b) {
	std::vector<Point3> points(m);
	for (auto& p : points) std::cin >> p.x >> p.y >> p.z;
	append_points(points, a, b, n);
	std::sort(points.begin(), points.end(), [](const Point3& a, const Point3& b) {return (a.z == b.z) ? a.x > b.x : a.z < b.z; });
	std::vector<NonChainablePoints> sets(m + n);
	for (const auto point : points) {
		const Point2 p{ point.x, point.y };
		auto left = 0;
		auto right = sets.size();
		while (left < right) {
			auto mid = (left + right) / 2;
			if (sets[mid].can_chain(p)) left = mid + 1;
			else right = mid;
		}
		sets[right].insert(p);
	}
	for (auto i = 0; i < sets.size(); ++i) {
		if (sets[i].is_empty()) return i;
	}
	return sets.size();
}
int main() {
	std::vector<int>result;
	while (true) {
		int m, n, a, b;
		std::cin >> m >> n >> a >> b;
		if (m == 0 && n == 0) break;
		result.push_back(solve(m, n, a, b));
	}
	for (const auto r : result) std::cout << r << '\n';
}