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

const long long INF = 1000000000000000007ll;
const int size = 200004;
const int treeSize = 2000004;

struct Point {
	long long x, y;
	Point() : x(0), y(0) {} ;
	Point(long long a, long long b) : x(a), y(b) {}
};

int n, m, counterY = 0, act = 0, p = 1, G[size];
long long w, h, Y[2*size], V[treeSize], MaxV[treeSize];
long long P[size], S[size];
map<long long, int> Mx, My;
pair<pair<long long, long long>, pair<int, int> > action[treeSize];

long long det(Point a, Point b) {
	return a.x*b.y-a.y*b.x;
}

long long add(int v, long long value) {
	v += p-1;
	int leaf = v;
	int counter = 0;
	G[counter++] = leaf;
	long long result = max(V[v], MaxV[v]);
	//printf("przed policzniem result: %lld \n", result);
	v = (v-1)/2;
	while(v!=0) {
		result += V[v];
		result = max(result, MaxV[v]);
		G[counter++] = v;
		v = (v-1)/2;
	}
	//printf("policzony result:%lld \n", result);
	result += value;
	for(int i = counter-1; i>=0; i--) {
		int where = G[i];
		if(where<p-1) {
			//printf("przepchnij z %d wartosc %lld\n", where, V[where]);
			V[2*where+1] += V[where];
			V[2*where+2] += V[where];
			MaxV[2*where+1] += V[where];
			MaxV[2*where+2] += V[where];
			V[where] = 0;
			MaxV[2*where+1] = max(MaxV[where], MaxV[2*where+1]);
			MaxV[2*where+2] = max(MaxV[where], MaxV[2*where+2]);
			MaxV[where] = -INF;
		}
		if(where%2) {
			V[where+1] += value;
			MaxV[where+1] += value;
		}
		if(where%2 == 0) MaxV[where-1] = max(MaxV[where-1], result);
	}
	MaxV[leaf] = V[leaf] = result;
	return result;
}

int main() {
	scanf("%d %d", &n, &m);
	scanf("%lld %lld", &w, &h);
	for(int i = 0; i<n; i++) {
		long long x, y, v;
		scanf("%lld %lld %lld", &x, &y, &v);
		long long newX = det(Point(-w, -h), Point(x, y));
		long long newY = det(Point(-w, h), Point(x, y));
		Y[counterY++] = newY;
		P[i] = v;
		action[act++] = make_pair(make_pair(newX, newY), make_pair(1, i));
	}
	for(int i = 0; i<m; i++) {
		long long x, y, v;
		scanf("%lld %lld %lld", &x, &y, &v);
		long long newX = det(Point(-w, -h), Point(x, y));
		long long newY = det(Point(-w, h), Point(x, y));
		Y[counterY++] = newY;
		S[i] = v;
		action[act++] = make_pair(make_pair(newX, newY), make_pair(-1, i));
	}
	sort(Y, Y+counterY);
	//printf("%d\n", counterY);
	counterY = unique(Y, Y+counterY)-Y;
	//printf("%d\n", counterY);
	for(int i = 0; i<counterY; i++) My.insert(make_pair(Y[i], i));
	p = 1;
	while(p<=counterY) p *= 2;
	for(int i = 0; i<=2*p; i++) MaxV[i] = -INF;
	sort(action, action+act);
	long long result = 0;
	for(int i = 0; i<act; i++) {
		pair<pair<long long, long long>, pair<int, int> > x = action[i];
		if(x.s.f == -1) { //straznik
			//printf("straznik %lld jego numer na drzewie to: %d\n", S[x.s.s], My[x.f.s]);
			long long r = add(My[x.f.s], -S[x.s.s]);
			//printf("%lld\n", r);
		} else { //przedmiot
			//printf("przedmiot %lld jego numer na drzewie to: %d\n", P[x.s.s], My[x.f.s]);
			long long r = add(My[x.f.s], P[x.s.s]);
			//printf("%lld\n", r);
		}
		/*for(int i = 0; i<2*p; i++) printf("%d ", i);
		printf("\n");
		for(int i = 0; i<2*p; i++) printf("%lld ", V[i]);
		printf("\n");
		for(int i = 0; i<2*p; i++) printf("%lld ", MaxV[i]);
		printf("\n");*/
		result = max(result, add(0, 0));
		//printf("%lld\n", result);
	}
	//result = max(result, add(0, 0));
	printf("%lld\n", result);
	return 0;
}