Submission #436041

#TimeUsernameProblemLanguageResultExecution timeMemory
436041dacin21Distributing Candies (IOI21_candies)C++17
100 / 100
619 ms27116 KiB
#include "candies.h" #include <bits/stdc++.h> using ll = int64_t; using namespace std; //really fast iterative segment-tree implementation template<class Segtree_Data> struct Segment_Tree{ using T = typename Segtree_Data::node_t; int n; vector<T>data; Segment_Tree(int n_) : n(n_), data(2*n, Segtree_Data::node_init()){ for(int i=n-1;i>=0;--i) data[i] = Segtree_Data::merge_nodes(data[i<<1], data[i<<1|1]); } Segment_Tree(vector<T> const&base) : n(base.size()), data(2*n, Segtree_Data::node_init()){ copy(base.begin(), base.end(), data.begin()+n); for(int i=n-1;i>=0;--i) data[i] = Segtree_Data::merge_nodes(data[i<<1], data[i<<1|1]); } void update(int pos, typename Segtree_Data::update_t const&val){ for(Segtree_Data::update_node(data[pos+=n], val); pos>>=1;){ data[pos] = Segtree_Data::merge_nodes(data[pos<<1], data[pos<<1|1]); } } void u(int pos, typename Segtree_Data::update_t const&val){ return update(pos,val); } T query(int l, int r) const { T retL = Segtree_Data::node_ne(), retR = Segtree_Data::node_ne(); for(l+=n, r+=n; l<r; l>>=1, r>>=1){ if(l&1) retL = Segtree_Data::merge_nodes(retL, data[l++]); if(r&1) retR = Segtree_Data::merge_nodes(data[--r], retR); } return Segtree_Data::merge_nodes(retL, retR); } T q(int l, int r) const { return query(l, r); } }; constexpr ll inf = 2e18; struct Node{ ll sum, min, max; }; struct Segtreedata{ typedef Node node_t; typedef int update_t; static constexpr node_t node_init() {return Node{0, 0, 0};} static constexpr node_t node_ne() {return Node{0, inf, -inf};} static node_t merge_nodes(node_t const&left, node_t const&right){ return node_t{ left.sum + right.sum, min(left.min, left.sum+right.min), max(left.max, left.sum+right.max) }; } static void update_node(node_t &node, update_t const&update){ node = node_t{update, min(update, 0), max(update, 0)}; } }; using Segtree = Segment_Tree<Segtreedata>; vector<int> distribute_candies(vector<int> c, vector<int> l, vector<int> r, vector<int> v) { const int n = c.size(); const int q = l.size(); vector<int> ret(n); vector<vector<int> > ev(n+1); for(int i=0; i<q; ++i){ ev[l[i]].push_back(i); ev[r[i]+1].push_back(-1-i); } Segtree st(q); for(int i=0; i<n; ++i){ for(auto const&e:ev[i]){ //cerr << "up " << e << "\n"; if(e >= 0) st.u(e, v[e]); else st.u(-1-e, 0); } int l = 0, r = q+1; auto span = st.q(0, q); if(span.max - span.min <= c[i]){ // start at 0 -> won't hit top boundary -> ans is sum - min ret[i] = span.sum - span.min; continue; } while(l+1 < r){ const int m = l + (r-l) / 2; span = st.q(m, q); if(span.max - span.min <= c[i]){ r = m; } else { l = m; } } span = st.q(l, q); //cerr << span.min << " " << span.max << " " << span.sum << "\n"; assert(span.min == 0 || span.max == 0); if(span.min == 0){ // won't hit bottom boundary -> ans is sum - max + c ret[i] = span.sum - span.max + c[i]; } else { // won't hit top boundary ret[i] = span.sum - span.min; } } return ret; }
#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...