Submission #1117911

#TimeUsernameProblemLanguageResultExecution timeMemory
1117911Zero_OPFood Court (JOI21_foodcourt)C++14
24 / 100
346 ms55368 KiB
#include <bits/stdc++.h>

using namespace std;

#define dbg(x) "[" #x " = " << (x) << "]"

struct fenwick_tree{
    vector<long long> bit;
    fenwick_tree(int n) : bit(n + 1, 0) {}

    void update(int i, long long v){
        for(; i < (int)bit.size(); i += i & (-i)) bit[i] += v;
    }

    long long query(int i){
        long long sum = 0;
        for(; i > 0; i -= i & (-i)) sum += bit[i];
        return sum;
    }

    long long query(int l, int r){
        return query(r) - query(l - 1);
    }

    int find_last(long long target){
        int i = 0;
        for(int b = 17; b >= 0; --b){
            if(i + (1 << b) < (int)bit.size() && target - bit[i + (1 << b)] > 0){
                i += (1 << b);
                target -= bit[i];
            }
        }
        return i + 1;
    }
};

struct min_prefix_segment_tree{ //finding minimum prefix with maximum position
    vector<long long> lazy;
    vector<pair<long long, int>> st;

    min_prefix_segment_tree(int n ): st(n << 2), lazy(n << 2) {}

    void build(int id, int l, int r){
        if(l == r) st[id] = {0, -l};
        else{
            int mid = l + r >> 1;
            build(id << 1, l, mid);
            build(id << 1 | 1, mid + 1, r);
            st[id] = min(st[id << 1], st[id << 1 | 1]);
        }
    }

    void apply(int id, long long v){
        st[id].first += v;
        lazy[id] += v;
    }

    void lazy_down(int id){
        if(lazy[id] != 0){
            apply(id << 1, lazy[id]);
            apply(id << 1 | 1, lazy[id]);
            lazy[id] = 0;
        }
    }

    void update(int id, int l, int r, int u, int v, long long val){
        if(u <= l && r <= v) apply(id, val);
        else{
            int mid = l + r >> 1;
            lazy_down(id);
            if(u <= mid) update(id << 1, l, mid, u, v, val);
            if(mid < v) update(id << 1 | 1, mid + 1, r, u, v, val);
            st[id] = min(st[id << 1], st[id << 1 | 1]);
        }
    }

    pair<long long, int> query(int id, int l, int r, int u, int v){
        if(u <= l && r <= v) return st[id];
        int mid = l + r >> 1;
        lazy_down(id);
        if(u > mid) return query(id << 1 | 1, mid + 1, r, u, v);
        if(mid >= v) return query(id << 1, l, mid, u, v);
        return min(query(id << 1, l, mid, u, v), query(id << 1 | 1, mid + 1, r, u, v));
    }
};

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

#ifdef LOCAL
    freopen("task.inp", "r", stdin);
    freopen("task.out", "w", stdout);
#endif // LOCAL

    int N, M, Q;
    cin >> N >> M >> Q;

    struct info_update{
        int type, c, k, id;
    };

    struct info_query{
        int id; long long b;
    };

    vector<vector<info_update>> updates(N);
    vector<vector<info_query>> queries(N);
    vector<int> color(Q + 1);

    for(int i = 1; i <= Q; ++i){
        int t;
        cin >> t;
        if(t == 1){
            int l, r, c, k;
            cin >> l >> r >> c >> k;
            --l;
            updates[l].push_back({+1, c, k, i});
            if(r < N) updates[r].push_back({-1, c, k, i});
            color[i] = c;
        } else if(t == 2){
            int l, r, k;
            cin >> l >> r >> k;
            --l;
            updates[l].push_back({+2, -1, k, i});
            if(r < N) updates[r].push_back({-2, -1, k, i});
        } else if(t == 3){
            int a; long long b;
            cin >> a >> b;
            --a;
            queries[a].push_back({b, i});
        }
    }

    min_prefix_segment_tree tr(Q + 1);
    fenwick_tree ft(Q), f(Q), g(Q);

    tr.build(1, 0, Q);

    //ft : 1 and 2
    //f  : only 1
    //g  : only 2

    vector<int> answer(Q + 1, -1);

    for(int i = 0; i < N; ++i){
        for(auto [type, c, k, id] : updates[i]){
            if(abs(type) == 1){
                if(type < 0) tr.update(1, 0, Q, id, Q, -k), f.update(id, -k);
                if(type > 0) tr.update(1, 0, Q, id, Q, +k), f.update(id, +k);
            } else if(abs(type) == 2){
                if(type < 0) tr.update(1, 0, Q, id, Q, +k), g.update(id, -k);
                if(type > 0) tr.update(1, 0, Q, id, Q, -k), g.update(id, +k);
            } else assert(false);
        }

        for(auto [b, id] : queries[i]){
            long long minPrefix; int from;
            tie(minPrefix, from) = tr.query(1, 0, Q, 0, id);
            from = -from;

            long long f_sum = f.query(id);
            long long g_sum = g.query(id);
            long long prefixSum = f_sum - g_sum;
            long long cur = prefixSum - minPrefix;

            if(cur < b){
                answer[id] = 0;
            } else{
                long long loss = (g_sum - g.query(from)) + f.query(from) + b;
                answer[id] = color[f.find_last(loss)];
            }
        }
    }

    for(int i = 1; i <= Q; ++i){
        if(answer[i] != -1) cout << answer[i] << '\n';
    }

    return 0;
}

Compilation message (stderr)

foodcourt.cpp: In constructor 'min_prefix_segment_tree::min_prefix_segment_tree(int)':
foodcourt.cpp:39:34: warning: 'min_prefix_segment_tree::st' will be initialized after [-Wreorder]
   39 |     vector<pair<long long, int>> st;
      |                                  ^~
foodcourt.cpp:38:23: warning:   'std::vector<long long int> min_prefix_segment_tree::lazy' [-Wreorder]
   38 |     vector<long long> lazy;
      |                       ^~~~
foodcourt.cpp:41:5: warning:   when initialized here [-Wreorder]
   41 |     min_prefix_segment_tree(int n ): st(n << 2), lazy(n << 2) {}
      |     ^~~~~~~~~~~~~~~~~~~~~~~
foodcourt.cpp: In member function 'void min_prefix_segment_tree::build(int, int, int)':
foodcourt.cpp:46:25: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   46 |             int mid = l + r >> 1;
      |                       ~~^~~
foodcourt.cpp: In member function 'void min_prefix_segment_tree::update(int, int, int, int, int, long long int)':
foodcourt.cpp:69:25: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   69 |             int mid = l + r >> 1;
      |                       ~~^~~
foodcourt.cpp: In member function 'std::pair<long long int, int> min_prefix_segment_tree::query(int, int, int, int, int)':
foodcourt.cpp:79:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   79 |         int mid = l + r >> 1;
      |                   ~~^~~
foodcourt.cpp: In function 'int main()':
foodcourt.cpp:131:35: warning: narrowing conversion of 'b' from 'long long int' to 'int' [-Wnarrowing]
  131 |             queries[a].push_back({b, i});
      |                                   ^
foodcourt.cpp:147:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  147 |         for(auto [type, c, k, id] : updates[i]){
      |                  ^
foodcourt.cpp:157:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  157 |         for(auto [b, id] : queries[i]){
      |                  ^
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...