Target Practice II

Target Practice II

这题经过手玩数据,我们发现,这里的每一个右上节点必须是负斜率,而右下节点必须是正斜率。

通过这个点我们就可以直接判断有无解,就是根据正负数的个数。

左端点的横坐标相同,这是一个非常特殊的点,这就可以得出一个明显的结论,越上面的尽量选斜率正的,越下面的尽量选斜率是负的。

这样我们就可以对每一个点选择斜率的正负了。

当然这里已经明示了可以使用二分,但是有点可惜,我们不能直接二分答案,这样做太难写了。

那我们就可以最小化最大的纵坐标和最大化最小的纵坐标,二分两次。

那这个 check 怎么写呢?我们用一个贪心的选择这个点需要的斜率,对于最大纵坐标,我们只需要考虑斜率是负的就可以了。对于每一个点需要选择负斜率的,我们就恰给他一个小于等于这个 (midy)/x 的最大值,就是 upper_bound-1,如果有一个点它选不了斜率,那就是这个否掉即可。反之亦可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=4E5+5;
int n,T,x1;
struct node {
	int x,y;
	bool operator<(const node &a )const {
		return y<a.y ;
	}
};
vector<node>ea,eb,ec;
multiset<int>st1,st2;
void init() {
	ea.clear();
	eb.clear();
	ec.clear();
	st1.clear(),st2.clear();
}
bool check1(int mid) {
	multiset<int> st = st1;
	for (node t : ea) {
		int s = (t.y - mid) / t.x;
		auto k = st.upper_bound(s);
		if (k == st.begin()) return false;
		k--;
		st.erase(k);
	}
	return true;
}
bool check2(int mid) {
	multiset<int> st = st2;
	for (node t : eb) {
		int s = (t.y - mid) / t.x;
		auto k = st.lower_bound(s);
		if (k == st.end()) return false;
		st.erase(k);
	}
	return true;
}
signed main() {
	scanf("%lld",&T);
	while(T--) {
		init();
		scanf("%lld%lld",&n,&x1);
		for(int i=1,y1,y2,x2; i<=n; i++) {
			scanf("%lld%lld%lld",&y1,&y2,&x2);
			ea.push_back({x2,y1});//右下
			eb.push_back({x2,y2});//右上
			ec.push_back({x1,y1});
			ec.push_back({x1,y2});
		}
		sort(ec.begin(),ec.end());
		for(int i=1,k; i<=4*n; i++) {
			scanf("%lld",&k);
			if(k>0)st1.insert(k);
			else st2.insert(k);
		}
		if(st1.size()<n || st2.size()<n) {
			puts("-1");
			continue;
		}
		int cnt=n;
		for (node t : ec) {
			if (cnt < st2.size()) eb.push_back(t), cnt++; 
			else ea.push_back(t);
		}
		int l=-1e18,r=ec[0].y,upans=0,downans=0;
		//这里二分下端点
		while(l<=r) {
			int mid=l+r>>1;
			if(check1(mid)) {
				downans=mid;
				l=mid+1;
			} else r=mid-1;
		}
		l=ec.back().y ,r=1e18;
		//这里二分上端点
		while(l<=r) {
			int mid=l+r>>1;
			if(check2(mid)) {
				upans=mid;
				r=mid-1;
			} else l=mid+1;
		}
		cout<<upans-downans<<endl;
	}
	return 0;
}

posted @   hnczy  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示