Submission #285251

#TimeUsernameProblemLanguageResultExecution timeMemory
285251user202729Aliens (IOI16_aliens)C++17
4 / 100
2 ms384 KiB
// moreflags=grader.cpp
// {}

#include "aliens.h"
// 15
#include<algorithm>
#include<cmath>
#include<cstdint>
#include<climits>
#include<cfloat>
#if not LOCAL
#define NDEBUG
#endif
#include<cassert>

long long take_photos(int n, int m, int numPhoto, std::vector<int> r, std::vector<int> c) {
	std::vector<std::pair<int, int>> points(r.size());
	for(int index=0; index<(int)r.size(); ++index)
		points[index]=std::minmax({r[index], c[index]});
	std::sort(begin(points), end(points),
			[&](auto first, auto sec){return first.first!=sec.first ? first.first<sec.first: first.second>sec.second;
			});
	{ // keep only extreme points
		auto out=points.begin()+1;
		std::for_each(out, points.end(),[&](auto it){
			assert(it.first>=out[-1].first);
			if(it.second>out[-1].second){
				assert(it.first>out[-1].first);
				*out++=it;
			}
		});
		points.erase(out, points.end());
	}
	r.clear(); c.clear(); n=-1;

	auto const square=[&](int it)->int64_t{return (int64_t)it*it;};

	auto const check=[&](double slope)->std::pair<int64_t, int>{
		std::vector<std::pair<double, int>> value(points.size()+1);
		value[0]={0, 0};
		for(int pos=1; pos<=(int)points.size(); ++pos){
			auto& cur=value[pos];
			cur={DBL_MAX, 0};
			for(int last=0; last<pos; ++last){
				cur=std::min(cur, std::make_pair(
					value[last].first
					+(double)square(points[pos-1].second-points[last].first+1)
					-(double)square(last==0 ? 0: std::max(0, points[last-1].second-points[last].first+1))
					+slope
					, value[last].second+1));
			}
		}
		auto const [result, resultf]=value[points.size()];
		return {(int64_t)std::round(result-resultf*slope), resultf};
	};

	// the numPhoto>=(int)points.size() case can be special-handled
	double slope1=0;
	auto [v1, nf1]=check(slope1);
	assert(nf1>=(int)points.size());
	nf1=std::max(numPhoto, nf1);

	double slope2; int64_t v2; int nf2;
	for(slope2=1;; slope2*=2){
		std::tie(v2, nf2)=check(slope2);
		if(nf2<=numPhoto) break;
	}

	while(true){
		assert(nf2<=numPhoto); assert(numPhoto<=nf1);
		if(nf1==numPhoto and nf2==numPhoto){
			assert(v1==v2);
			return v1;
		}

		int64_t const lower=(int64_t)std::ceil(
				std::max(
					(double)v1+slope1*(nf1-numPhoto),
					(double)v2+slope2*(nf2-numPhoto)
					)-1e-12);
		assert(nf1>nf2);
		int64_t const upper=(v1*(numPhoto-nf2)+v2*(nf1-numPhoto))/(nf1-nf2);
		assert(upper>=0);
		assert(lower<=upper);

		if(lower==upper) return lower;

		assert(nf2<numPhoto); assert(numPhoto<nf1);
		auto const [v3, nf3]=check(slope2);
		(nf3<=numPhoto ? std::tie(v1, nf1): std::tie(v2, nf2))=std::pair(v3, nf3);
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...