답안 #800639

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
800639 2023-08-01T17:13:33 Z _martynas 사탕 분배 (IOI21_candies) C++17
100 / 100
1233 ms 50820 KB
#include "candies.h"
#include <vector>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <cstdio>

using namespace std;

#warning change mxn back
const int mxn = 2e5+5;
using ll = long long;

const ll inf = 2e18;
const ll smaller_inf = 1e18;


struct Node {
    ll mx = -inf, mn = inf;
    int mxi = -100, mni = -100;
    ll tag = 0;
    Node() {}
    Node(int i) {
        mx = mn = 0;
        mxi = mni = i;
    }
    Node join(Node rhs) {
        Node lhs = *this;
        lhs.tag = 0;
        if(rhs.mx > lhs.mx) {
            lhs.mx = rhs.mx;
            lhs.mxi = rhs.mxi;
        }
        if(rhs.mn < mn) {
            lhs.mn = rhs.mn;
            lhs.mni = rhs.mni;
        }
        return lhs;
    }
};

int n, q;

struct Seg {
private:
    Node A[4*mxn];
    void inc_tag(int u, ll inc) {
        A[u].tag += inc;
        A[u].mx += inc, A[u].mn += inc;
    }

    void build(int u, int l, int r) {
        if(l == r) {
            A[u] = Node(l);
            return;
        }
        int m = (l+r+4)/2-2;
        build(2*u, l, m), build(2*u+1, m+1, r);
        pull(u);
    }

    void push(int u) {
        inc_tag(2*u, A[u].tag);
        inc_tag(2*u+1, A[u].tag);
        A[u].tag = 0;
    }

    void pull(int u) {
        A[u] = A[2*u].join(A[2*u+1]);
    }

    void range_add(int u, int l, int r, int ql, int qr, ll val) {
        if(qr < l || ql > r) return;
        if(ql <= l && r <= qr) {
            inc_tag(u, val);
            return;
        }
        push(u);
        int m = (l+r+4)/2-2;
        range_add(2*u, l, m, ql, qr, val);
        range_add(2*u+1, m+1, r, ql, qr, val);
        pull(u);
    }

    Node get(int u, int l, int r, int ql, int qr) {
        if(qr < l || ql > r) return Node{};
        if(ql <= l && r <= qr) {
            return A[u];
        }
        push(u);
        int m = (l+r+4)/2-2;
        return get(2*u, l, m, ql, qr).join(get(2*u+1, m+1, r, ql, qr));
    }

public:
    void build() {
        build(1, -2, q-1);
    }
    void range_add(int l, int r, ll val) {
        range_add(1, -2, q-1, l, r, val);
    }

    Node get(int l, int r) {
        return get(1, -2, q-1, l, r);
    }
};

vector<int> distribute_candies(vector<int> c, vector<int> l,
                                    vector<int> r, vector<int> v) {
    n = c.size();
    q = l.size();
    vector<int> s(n);
    struct Event {
        int t, delta;
    };
    vector<vector<Event>> events(n);
    for(int i = 0; i < q; i++) {
        events[l[i]].push_back(Event{i, v[i]});
        if(r[i] < n-1)
            events[r[i]+1].push_back(Event{i, -v[i]});
    }
    Seg seg;
    seg.build();
    seg.range_add(-2, q-1, smaller_inf);
    seg.range_add(-1, q-1, -smaller_inf);
    for(int i = 0; i < n; i++) {
        for(auto e : events[i]) {
            seg.range_add(e.t, q, e.delta);
        }
        int lo = -2, hi = q-1;
        while(lo < hi) {
            int m = (lo+hi+5)/2-2;
            auto node = seg.get(m, q-1);
            if(node.mx-node.mn < c[i]) {
                hi = m-1;
            }
            else {
                lo = m;
            }
        }
        auto node = seg.get(lo, q-1);
        if(node.mni < node.mxi) {
            // increased, hit max capacity, decreased without going lower than 0
            s[i] = c[i]-(node.mx-seg.get(q-1, q-1).mx);
        }
        else {
            // decreased, hit 0, increased without going above capacity
            s[i] = seg.get(q-1, q-1).mx-node.mn;
        }
    }
    return s;
}

//namespace Tests {
//    void test_segment_tree() {
//        Seg s;
//        vector<int> arr = {2, 4, 1, 1, -2, 5, 2};
//        q = arr.size();
//        s.build();
//        for(int i = 0; i < (int)arr.size(); i++) {
//            s.range_add(i, i, arr[i]);
//        }
//        for(int i = 0; i < 10; i++) {
//            int a = rand() % q, b = rand() % q;
//            if(a > b) swap(a, b);
//            ll delta = rand()%11-5;
//            s.range_add(a, b, delta);
//            for(int j = a; j <= b; j++) arr[j] += delta;
//        }
//        vector<pair<int, int>> ranges;
//        for(int i = 0; i < 10; i++) {
//            int a = rand() % q, b = rand() % q;
//            if(a > b) swap(a, b);
//            ranges.push_back({a, b});
//        }
//        for(auto p : ranges) {
//            Node res = s.get(p.first, p.second);
//            printf("(%d, %d) max: %lld (%d), min: %lld (%d)\n", p.first, p.second,
//                   res.mx, res.mxi, res.mn, res.mni);
//            auto it_max = max_element(arr.begin()+p.first, arr.begin()+p.second+1);
//            auto it_min = min_element(arr.begin()+p.first, arr.begin()+p.second+1);
//            assert(res.mx == *it_max);
//            assert(res.mn == *it_min);
//            assert(res.mxi == distance(arr.begin(), it_max));
//            assert(res.mni == distance(arr.begin(), it_min));
//        }
//        for(int i = 0; i < (int)arr.size(); i++) {
//            Node res = s.get(i, i);
//            printf("i = %d:\nmax: %lld (%d), min: %lld (%d)\n", i, res.mx, res.mxi, res.mn, res.mni);
//        }
//    }
//}

Compilation message

candies.cpp:10:2: warning: #warning change mxn back [-Wcpp]
   10 | #warning change mxn back
      |  ^~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 25300 KB Output is correct
2 Correct 13 ms 25340 KB Output is correct
3 Correct 13 ms 25344 KB Output is correct
4 Correct 14 ms 25428 KB Output is correct
5 Correct 18 ms 25428 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1140 ms 44132 KB Output is correct
2 Correct 1117 ms 48092 KB Output is correct
3 Correct 1122 ms 48036 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 14 ms 25300 KB Output is correct
2 Correct 213 ms 34588 KB Output is correct
3 Correct 353 ms 34860 KB Output is correct
4 Correct 1185 ms 50036 KB Output is correct
5 Correct 1176 ms 50432 KB Output is correct
6 Correct 1167 ms 50820 KB Output is correct
7 Correct 1155 ms 50168 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 25248 KB Output is correct
2 Correct 12 ms 25300 KB Output is correct
3 Correct 110 ms 32212 KB Output is correct
4 Correct 352 ms 33676 KB Output is correct
5 Correct 954 ms 42168 KB Output is correct
6 Correct 1010 ms 42112 KB Output is correct
7 Correct 1014 ms 42228 KB Output is correct
8 Correct 990 ms 42192 KB Output is correct
9 Correct 968 ms 42176 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 25300 KB Output is correct
2 Correct 13 ms 25340 KB Output is correct
3 Correct 13 ms 25344 KB Output is correct
4 Correct 14 ms 25428 KB Output is correct
5 Correct 18 ms 25428 KB Output is correct
6 Correct 1140 ms 44132 KB Output is correct
7 Correct 1117 ms 48092 KB Output is correct
8 Correct 1122 ms 48036 KB Output is correct
9 Correct 14 ms 25300 KB Output is correct
10 Correct 213 ms 34588 KB Output is correct
11 Correct 353 ms 34860 KB Output is correct
12 Correct 1185 ms 50036 KB Output is correct
13 Correct 1176 ms 50432 KB Output is correct
14 Correct 1167 ms 50820 KB Output is correct
15 Correct 1155 ms 50168 KB Output is correct
16 Correct 13 ms 25248 KB Output is correct
17 Correct 12 ms 25300 KB Output is correct
18 Correct 110 ms 32212 KB Output is correct
19 Correct 352 ms 33676 KB Output is correct
20 Correct 954 ms 42168 KB Output is correct
21 Correct 1010 ms 42112 KB Output is correct
22 Correct 1014 ms 42228 KB Output is correct
23 Correct 990 ms 42192 KB Output is correct
24 Correct 968 ms 42176 KB Output is correct
25 Correct 13 ms 25300 KB Output is correct
26 Correct 334 ms 33756 KB Output is correct
27 Correct 222 ms 37204 KB Output is correct
28 Correct 1133 ms 48688 KB Output is correct
29 Correct 1191 ms 49076 KB Output is correct
30 Correct 1161 ms 49260 KB Output is correct
31 Correct 1157 ms 49456 KB Output is correct
32 Correct 1233 ms 49644 KB Output is correct