답안 #471313

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
471313 2021-09-08T09:14:14 Z Soapen Deda (COCI17_deda) C++17
140 / 140
209 ms 3432 KB
// freopen("../../p257.t13.in", "r", stdin);

#include <bits/stdc++.h>

#define rep(a, b)   for(int a = 0; a < (b); ++a)
#define all(a)      (a).begin(),(a).end()
#define endl        '\n'

using namespace std;
using Graph = vector<vector<int>>;
using ll = long long;

namespace cpc {

int floor_log2(int n) { return n ? 31 - __builtin_clz(n) : 0; }
int ceil_log2(int n) { return floor_log2(n) + (__builtin_popcount(n)!=1); }

template<class Conf>
struct SegTreeImpl {
    using T = typename Conf::T; // data type
    using U = typename Conf::U; // update type

    int width(int v) { return (int)n >> floor_log2(v); }
    int left(int v) { return width(v) * (v ^ (1 << floor_log2(v))); }
    int right(int v) { return left(v) + width(v); }

    int n;
    vector<T> d; // node values
    vector<U> lazy; // exclusive lazy

    SegTreeImpl(int _n) : n(1 << ceil_log2(_n)), d(2*n, Conf::NEUTRAL) {
        if constexpr(Conf::LAZY) lazy.resize(2*n, Conf::UNCHANGED);
    }

    void update(int i, T val) {
        flush(n+i);
        d[n+i]= val;
        rebuild(n+i);
    }

    void update(int l, int r, const U& upd) {
        flush(n + l);
        flush(n + r - 1);

        for (int li=n+l, ri =n+r; li<ri; li/=2, ri/=2) {
            if (li % 2) Conf::apply(*this, li++, upd);
            if (ri % 2) Conf::apply(*this, --ri, upd);
        }

        rebuild(trunc(n+l)); // rebuild above first changed nodes
        rebuild(trunc(n+r)-1);
    }

    T& query(int i) {
        flush(n + i);
        return d[n+i];
    }

    T query(int l, int r) {
        flush(n + l);
        flush(n + r - 1);
        T rl = Conf::NEUTRAL, rr = Conf::NEUTRAL;
        for(l+=n, r+=n; l<r; l/=2, r/=2) {
            if(l&1) rl = Conf::combine(rl, d[l++]);
            if(r&1) rr = Conf::combine(d[--r], rr);
        }
        return Conf::combine(rl, rr);
    }

    template <class Pred>
    int lower_bound(Pred pred) {
        if (!pred(d[1])) return -1;
        T pref = Conf::NEUTRAL;
        int i = 1;
        while (i<n) {
            push(i);
            if(!pred(Conf::combine(pref, d[i*=2])))
                pref = Conf::combine(pref, d[i++]);
        }
        return i - n;
    }

    template <class Pred>
    T lower_bound(int l, int r, Pred pred) {
        vector<int> segs, rsegs;
        for(l+=n, r+=n; l<r; l/=2, r/=2) {
            if(l&1) segs.push_back(l++);
            if(r&1) rsegs.push_back(--r);
        }
        segs.insert(end(segs), rbegin(rsegs), rend(rsegs));
        T acc = Conf::NEUTRAL;
        for(auto v : segs) {
            if(pred(Conf::combine(acc,d[v]))) {
                // find it in v
                while(v<n) {
                    if(!pred(Conf::combine(acc,d[2*v])))
                        acc = Conf::combine(acc,d[2*v]), v = 2*v+1;
                    else
                        v = 2*v;
                }
                return v-n;
            }
            acc = Conf::combine(acc,d[v]);
        }
        return -1;
    }

private:

    // push lazy down one layer
    void push(int v) {
        if constexpr(Conf::LAZY) {
            if(lazy[v]==Conf::UNCHANGED) return;
            Conf::apply(*this, 2*v, lazy[v]);
            Conf::apply(*this, 2*v+1, lazy[v]);
            lazy[v] = Conf::UNCHANGED;
        }
    }

    // push lazy updates of all parents down to v
    void flush(int v) {
        if constexpr(Conf::LAZY) {
            for(int b = floor_log2(v); b; --b)
                push(v>>b);
        };
    }

    // rebuild v and all its parents
    void rebuild(int v) {
        while(v/=2) d[v] = Conf::combine(d[2*v], d[2*v+1]);
    }

    // shifts all trailing zeros away; (= first parent of v that is touched in query)
    int trunc(int v) { return v >> __builtin_ctz(v); }

};

}

const int INF = 1e9+7;
struct SegTreeConf {
    using T = int;
    static constexpr T NEUTRAL = INF;
    static T combine(const T& a, const T& b) { return min(a,b); }

    // lazy part
    const static bool LAZY = false;
    using U = int;
    static constexpr U UNCHANGED = 0;
    void static apply(cpc::SegTreeImpl<SegTreeConf>& seg, int v, const U& upd) {
        seg.d[v] += seg.width(v)*upd;
        seg.lazy[v] += upd;
    }
};
using SegTree = cpc::SegTreeImpl<SegTreeConf>;



int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.precision(10);

    int n,q; cin>>n>>q;
    SegTree seg(n);

    rep(m,q) {
        char t; cin>>t;
        if(t=='M') {
            int x,i; cin>>x>>i;
            seg.update(i-1,x);
        } else {
            int max_stops,min_age; cin>>max_stops>>min_age;
            min_age--;
            int res = seg.lower_bound(min_age, n, [&](int acc) {
                return acc <= max_stops;
            });
            cout << (res==-1 ? -1 : res+1) << endl;
        }
    }

    return 0;
}

# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 204 KB Output is correct
2 Correct 1 ms 204 KB Output is correct
3 Correct 4 ms 204 KB Output is correct
4 Correct 190 ms 3360 KB Output is correct
5 Correct 145 ms 2040 KB Output is correct
6 Correct 209 ms 3432 KB Output is correct
7 Correct 169 ms 3264 KB Output is correct