【BZOJ3716】[PA2014]Muzeum(坐标旋转)(贪心)(最大权闭合子图)

贪心 同时被 2 个专栏收录
41 篇文章 0 订阅
25 篇文章 0 订阅

传送门


题解:

首先这道题的最大权闭合子图模型是很显然的,但是我们并不能建图拿来跑最大流。

考虑利用图的特殊性质把最大流贪心流出来。

首先所有坐标乘上余切然后旋转,把一个警卫看得到的所有手办放到左上方向。

将所有点按照横坐标从小到大排序。

处理一个警卫之前先把所有横坐标比他小的加入,然后从纵坐标最小的能流的开始贪心流就行了。

这样贪心的正确性是显然的,考虑我们把一个在较大纵坐标流的放到一个较小纵坐标流,那么显然后面纵坐标更大的能流的就更多,这样的操作不会使答案变坏。


代码:

#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;
}
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值