제출 #285272

#제출 시각아이디문제언어결과실행 시간메모리
285272user202729Aliens (IOI16_aliens)C++17
41 / 100
2085 ms5672 KiB
// moreflags=grader.cpp // it's too late. // at least read the warning messages... #include "aliens.h" // 15 #include<algorithm> #include<map> #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}; auto const t=[&](int last)->double{ return value[last].first -(double)square(last==0 ? 0: std::max(0, points[last-1].second-points[last].first+1)) +(double)square(points[last].first); }; struct Item{double t; int numPhoto;}; struct IntComparator; struct Query{ double slope; std::map<int, Item, IntComparator> const& hull; double operator()(int u, Item item)const{ return item.t + u* slope; } double operator()(typename std::map<int, Item>::value_type const& x)const{ return (*this)(x.first, x.second); } }; struct IntComparator //: std::less<int> { // !?!? using is_transparent=int; bool operator()(Query const& first, int sec) const{ auto const iterator=first.hull.find(sec); assert(iterator!=first.hull.end()); auto const next=std::next(iterator); return next==first.hull.end() or first(*iterator)<=first(*next); } bool operator()(int first, int sec) const{ return first<sec; } /* bool operator()(int sec, Query first) const{ return not (*this)(first, sec); } */ }; std::map<int, Item, IntComparator> hull; auto const add=[&](int pos)->void{ int const u=points[pos].first; double const t_=t(pos); auto const [iterator, inserted]=hull.insert({u, {t_, value[pos].second}}); if(not inserted){ if(t_>=iterator->second.t) return; iterator->second.t=t_; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" assert(iterator->second.t==t_); #pragma GCC diagnostic pop auto const bad=[&](auto iterator){ auto [u1_, i1]=*std::prev(iterator); auto [u2_, i2]=*iterator; auto [u3_, i3]=*std::next(iterator); assert(u1_<u2_); assert(u2_<u3_); auto const u1=u1_-u2_, u3=u3_-u2_; double const t1=i1.t-i2.t; double const t3=i3.t-i2.t; return u3*t1-u1*t3<=0; }; if(iterator!=hull.begin() and std::next(iterator)!=hull.end() and bad(iterator)){ hull.erase(iterator); return; } while(std::next(iterator)!=hull.end() and std::next(std::next(iterator))!=hull.end() and bad(std::next(iterator))) hull.erase(std::next(iterator)); while(iterator!=hull.begin() and std::prev(iterator)!=hull.begin() and bad(std::prev(iterator))) hull.erase(std::prev(iterator)); }; auto const query=[&](double slope){ std::pair<double, int> cur{DBL_MAX, 0}; /* for(auto [u, item]: hull){ cur=std::min(cur, std::make_pair( item.t + u* slope , item.numPhoto +1)); } */ Query q{slope, hull}; auto iterator=hull.upper_bound(q); if(iterator==hull.end()) --iterator; //auto [u, item]=*iterator; cur=std::make_pair(q(*iterator) , iterator->second.numPhoto +1); return cur; }; add(0); for(int pos=1; ; ++pos){ auto& cur=value[pos]; cur={DBL_MAX, 0}; double const tmp2=-double(points[pos-1].second+1)*2; /* for(int last=0; last<pos; ++last){ cur=std::min(cur, std::make_pair( (double)t(last) + points[last].first * tmp2 , value[last].second+1)); } */ cur=query(tmp2); cur.first+=tmp2*tmp2/4+slope; if(pos==(int)points.size()) break; add(pos); } 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); if(numPhoto>=nf1) return v1; assert(nf1>=(int)points.size()); 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 slope3=(slope1+slope2)/2; auto const [v3, nf3]=check(slope3); (nf3<=numPhoto ? std::tie(v2, nf2, slope2): std::tie(v1, nf1, slope1))=std::tuple(v3, nf3, slope3); } }
#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...