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

using namespace std;

typedef long long int ll;

const ll minfty = -1e18;

typedef long double ld;
const ld eps = 1e-10;
inline bool rowne(ld a, ld b) { return abs(a - b) < eps; }
inline bool mniejsze(ld a, ld b) { return !rowne(a, b) && a < b; }
inline bool wieksze(ld a, ld b) { return !rowne(a, b) && a > b; }

int n, d, u;
int w, h;

struct punkt
{
	ld x, y;
	int war;
	punkt(int xx, int yy, int v) : war(v)
	{
		x = (xx + (((ld) w) * yy) / h) / (2.0L * w);
		y = ((((ld) w) * yy) / h - xx) / (2.0L * w);
	}

	void wypisz() const
	{
		printf("P(%.2Lf, %.2Lf : %d)\n", x, y, war);
	}
};

inline bool operator< (const punkt &a, const punkt &b)
{
	if(rowne(a.y, b.y))
		return mniejsze(a.x, b.x);
	return mniejsze(a.y, b.y);
}

vector<punkt> punkty;

vector<ld> iksy;
inline int pos(ld iks) { return lower_bound(iksy.begin(), iksy.end(), iks, mniejsze) - iksy.begin(); }

int n2;

ll drz[1200005];
ll spu[1200005];

void spusc(int w)
{
	drz[w] += spu[w];
	if(w < n2)
	{
		spu[w * 2] += spu[w];
		spu[w * 2 + 1] += spu[w];
	}
	spu[w] = 0LL;
}

void dodaj(int w, int a, int b, int p, int k, ll war)
{
	spusc(w);
	if(b < p || k < a)
		return;
	if(a <= p && k <= b)
	{
		spu[w] = war;
		spusc(w);
		return;
	}
	dodaj(w * 2, a, b, p, (p + k) / 2, war);
	dodaj(w * 2 + 1, a, b, (p + k) / 2 + 1, k, war);
	drz[w] = max(drz[w * 2], drz[w * 2 + 1]);
}

ll odczytaj(int w, int a, int b, int p, int k)
{
	spusc(w);
	if(b < p || k < a)
		return minfty;
	if(a <= p && k <= b)
		return drz[w];
	return max(
		odczytaj(w * 2, a, b, p, (p + k) / 2),
		odczytaj(w * 2 + 1, a, b, (p + k) / 2 + 1, k)
	);
}

int main()
{
	scanf("%d%d", &d, &u);
	scanf("%d%d", &w, &h);
	n = d + u;
	for(int i = 0; i < n; i++)
	{
		int x, y, v;
		scanf("%d%d%d", &x, &y, &v);
		if(i >= d)
			v *= -1;
		punkty.push_back(punkt(x, y, v));
	}
	sort(punkty.begin(), punkty.end());
	for(const punkt &p : punkty)
		iksy.push_back(p.x);
	sort(iksy.begin(), iksy.end(), mniejsze);
	iksy.resize(unique(iksy.begin(), iksy.end(), rowne) - iksy.begin());
	n2 = 1;
	while(n2 <= iksy.size())
		n2 *= 2;
	for(const punkt &p : punkty)
	{
		int poz = pos(p.x);
		ll ile = odczytaj(1, poz, poz, 0, n2 - 1);
		ll pop = max(odczytaj(1, poz, n2 - 1, 0, n2 -1), 0LL);
		if(ile < pop)
			dodaj(1, poz, poz, 0, n2 - 1, pop - ile);
		dodaj(1, 0, poz, 0, n2 - 1, p.war);
	}
	printf("%lld\n", odczytaj(1, 0, n2 - 1, 0, n2 - 1));
	return 0;
}