Submission #1216308

#TimeUsernameProblemLanguageResultExecution timeMemory
1216308pbear289Wall (IOI14_wall)C++20
100 / 100
1206 ms235208 KiB
#include <cstdint> #include <numeric> #include <utility> #include <vector> #include "wall.h" namespace segment_tree { enum class query_type {UPD, SET, NONE}; template<typename T> struct query {query_type q=query_type::NONE; T v;}; template<typename T> struct node {T v; int64_t parent{-1}; int64_t l_child{-1}; int64_t r_child{-1}; int64_t len{1}; query<T> q;}; template<typename T,class comb,class upd=comb> class lazy_tree { public: // i'm so happy i can do this lazy_tree(int64_t n_=0,comb f_=comb(),upd g_=upd()):f(f_),g(g_),n(n_) { seg.resize(2*n); for(int64_t i=1;i<n;++i) { seg[i].parent=i/2; seg[i].l_child=2*i; seg[i].r_child=2*i+1; } seg[0].l_child=1; for(int64_t i=n;i<2*n;++i) {seg[i].parent=i/2;} for(int64_t i=n-1;i>=1;--i) { seg[i].len=seg[seg[i].l_child].len+seg[seg[i].r_child].len; } for(int64_t i=0;i<2*n;++i) {seg[i].v=id; seg[i].q.v=id;} } void update(int64_t a,int64_t b,T v) {__update_r_(0,n-1,seg[0].l_child,a,b,{query_type::UPD,v});} void set(int64_t a,int64_t b,T v) {__update_r_(0,n-1,seg[0].l_child,a,b,{query_type::SET,v});} T range_query(int64_t a,int64_t b) {return __query_r_(a,b,seg[0].l_child,0,n-1);} std::vector<node<T>> full_tree() {return seg;} private: // we assume that f and g share the same identity, otherwise we're a bit cooked comb f; upd g; int64_t n{0}; const T id{f.id}; std::vector<node<T>> seg; void __apply_(int64_t ptr,const query<T> &x) { if(x.q==query_type::UPD) { if(seg[ptr].q.q!=query_type::SET) { seg[ptr].q=query<T>({query_type::UPD,g(seg[ptr].q.v,x.v)}); } else { seg[ptr].q=query<T>({query_type::SET,g(seg[ptr].q.v,x.v)}); } seg[ptr].v=g(seg[ptr].v,x.v,seg[ptr].len); } else if(x.q==query_type::SET) { seg[ptr].v=g(id,x.v,seg[ptr].len); seg[ptr].q=x; } else {} } void __push_down_(int64_t ptr) { if(seg[ptr].l_child!=-1) { __apply_(seg[ptr].l_child,seg[ptr].q); __apply_(seg[ptr].r_child,seg[ptr].q); } else {} seg[ptr].q=query<T>(); seg[ptr].q.v=id; } void __update_r_(int64_t l,int64_t r,int64_t k,int64_t ql,int64_t qr,const query<T> &x) { if(qr<l||ql>r) {return;} if(ql<=l&&r<=qr) { __apply_(k,x); } else { __push_down_(k); int m=l+seg[seg[k].l_child].len-1; __update_r_(l,m,seg[k].l_child,ql,qr,x); __update_r_(m+1,r,seg[k].r_child,ql,qr,x); seg[k].v=f(seg[seg[k].l_child].v,seg[seg[k].r_child].v); } } T __query_r_(int64_t a,int64_t b,int64_t k,int64_t x,int64_t y) { if(b<x||a>y) {return id;} if(a<=x&&y<=b) {return seg[k].v;} __push_down_(k); int d=x+seg[seg[k].l_child].len-1; return f(__query_r_(a,b,seg[k].l_child,x,d),__query_r_(a,b,seg[k].r_child,d+1,y)); } }; }; template<typename T> using pmmx=std::pair<T,T>; // here, we represent a modification as f_{a,b}(x)=min(max(x,a),b); setting elements to c also corresponds to such an operation; in this case we let a=b=c. template<typename T> class minmax { public: pmmx<T> operator()(pmmx<T> a,pmmx<T> b,int k=1) { if(a.first>a.second) {a.first=a.second;} if(b.first>b.second) {b.first=b.second;} if(a.first<=b.first&&b.first<=a.second&&a.second<=b.second) { return {b.first,a.second}; } else if(b.first<=a.first&&a.first<=b.second&&b.second<=a.second) { return {a.first,b.second}; } else if(a.first<=b.first&&b.first<=b.second&&b.second<=a.second) { return b; } else if(b.first<=a.first&&a.first<=a.second&&a.second<=b.second) { return a; } else if(b.first<=b.second&&b.second<=a.first&&a.first<=a.second) { return {b.second,b.second}; } else if(a.first<=a.second&&a.second<=b.first&&b.first<=b.second) { return {b.first,b.first}; } else { return {0,0}; } } const pmmx<T> id{pmmx{std::numeric_limits<T>::min(),std::numeric_limits<T>::max()}}; }; void buildWall(int n, int k, int op[], int left[], int right[], int height[], int finalHeight[]) { segment_tree::lazy_tree<pmmx<int>,minmax<int>> segtree(n); for(int i=0;i<k;++i) { if(op[i]==1) { segtree.update(left[i],right[i],{height[i],std::numeric_limits<int>::max()}); } else { segtree.update(left[i],right[i],{std::numeric_limits<int>::min(),height[i]}); } } pmmx<int> func; for(int i=0;i<n;++i) { func=segtree.range_query(i,i); finalHeight[i]=std::min(std::max(0,func.first),func.second); } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...