传送门
题解:
首先这道题的最大权闭合子图模型是很显然的,但是我们并不能建图拿来跑最大流。
考虑利用图的特殊性质把最大流贪心流出来。
首先所有坐标乘上余切然后旋转,把一个警卫看得到的所有手办放到左上方向。
将所有点按照横坐标从小到大排序。
处理一个警卫之前先把所有横坐标比他小的加入,然后从纵坐标最小的能流的开始贪心流就行了。
这样贪心的正确性是显然的,考虑我们把一个在较大纵坐标流的放到一个较小纵坐标流,那么显然后面纵坐标更大的能流的就更多,这样的操作不会使答案变坏。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;T num;bool f=0;
while(!isdigit(c=gc()))f=c=='-';num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
using pll=std::pair<ll,ll>;
#define fi first
#define se second
cs int N=2e5+7;
int n,m;ll w,h,ans;
struct node{ll x,y,v;}a[N],b[N];
inline bool operator<(cs node &a,cs node &b){return a.x<b.x;}
std::set<pll> s;
signed main(){
#ifdef zxyoi
freopen("museum.in","r",stdin);
#endif
n=gi(),m=gi(),w=gi(),h=gi();
for(int re i=1;i<=n;++i){
ll x=gi()*h,y=gi()*w,v=gi();
a[i]=(node){x+y,x-y,v};ans+=v;
}std::sort(a+1,a+n+1);
for(int re i=1;i<=m;++i){
ll x=gi()*h,y=gi()*w,v=gi();
b[i]=(node){x+y,x-y,v};
}std::sort(b+1,b+m+1);
for(int re i=1,j=1;i<=m;++i){
while(j<=n&&a[j].x<=b[i].x)s.insert(pll(a[j].y,a[j].v)),++j;
auto it=s.lower_bound(pll(b[i].y,0));ll flow=b[i].v;
while(flow&&it!=s.end()){
auto q=*it;s.erase(it);
ll d=std::min(q.se,flow);
flow-=d,ans-=d,q.se-=d;
if(q.se)s.insert(q);
else it=s.lower_bound(pll(b[i].y,0));
}
}
cout<<ans<<"\n";
return 0;
}