Submission #1236994

#TimeUsernameProblemLanguageResultExecution timeMemory
123699412baaterHorses (IOI15_horses)C++20
100 / 100
279 ms63988 KiB
#include "horses.h"
#include <stack>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;
typedef long long ll;

const ll MOD = 1E9 + 7;
const int MAXN = 500050;
int n;
vector<int> x(MAXN);
vector<int> y(MAXN);
set<int> valid_indices;

struct ST {
    int n;
    vector<ll> seg;

    ST(int N) : seg(4*N) {
        int s = 1;
        for (; s < N; s <<= 1);
        n = N;

    }

    void update(int pos, int val) {
        pos += n;
        seg[pos] = val;
        pos >>= 1;
        while (pos > 0) {
            seg[pos] = (seg[pos*2] * seg[pos*2 + 1])%MOD;
            pos >>= 1;
        }
    }

    ll query(int l, int r) {
        l += n;
        r += n;
        ll ret = 1;
        while (l < r) {
            if (l&1) { ret *= seg[l++]; ret %= MOD; }
            if (r&1) { ret *= seg[--r]; ret %= MOD; }
            l >>= 1;
            r >>= 1;
        }
        return ret%MOD;
    }
};

struct maxST {
    ll n;
    vector<ll> seg;

    maxST(ll N) : seg(4*N) {
        int s = 1;
        for (; s < N; s <<= 1);
        n = s;
    }

    void update(ll pos, ll val) {
        pos += n;
        seg[pos] = val;
        pos >>= 1;
        while (pos > 0) {
            seg[pos] = max(seg[pos*2], seg[pos*2 + 1]);
            pos >>= 1;
        }
    }

    ll query(ll l, ll r) {
        l += n;
        r += n;
        ll ret = 0;
        while (l < r) {
            if (l&1) ret = max(ret, seg[l++]);
            if (r&1) ret = max(ret, seg[--r]);
            l >>= 1;
            r >>= 1;
        }
        return ret;
    }
};

ST tree(MAXN);
maxST maxTree(MAXN);

int find_best() {

    if (valid_indices.empty()) return maxTree.query(0,n);

    ll result = tree.query(0,n), sum = 0, last = n;
    for (auto it = valid_indices.rbegin(); it != valid_indices.rend(); it++) {
        int pos = *it;
        ll val = maxTree.query(pos, last);
        if (val > sum) {
            result = (tree.query(0, pos+1) * val) % MOD;
            sum = val;
        }
        sum *= x[pos];
        last = pos;
        if (sum > MOD) break;
    }

    if (sum < MOD) {
        ll a = maxTree.query(0, last);
        if (a > sum) {
            result = a;
        }
    }
    return result;
}


int solve() {
    // int num = max(0, n-1001);
    // int ind = find_best(num);
    // ll horseNum = tree.query(0, ind+1);
    // ll cashNum = y[ind];
    // cout << horseNum << " " << cashNum << endl;
    return find_best();
}


int init(int N, int X[], int Y[]) {
    n = N;
    for (int i = 0; i < N; i++) {
        x[i] = X[i];
        y[i] = Y[i];
        tree.update(i, x[i]);
        maxTree.update(i, y[i]);
        if (x[i] != 1) {
            valid_indices.insert(i);
        }
    }
    return solve();
}

int updateX(int pos, int val) {
    x[pos] = val;
    tree.update(pos, val);
    if (val == 1) {
        valid_indices.erase(pos);
    } else {
        valid_indices.insert(pos);
    }
    return solve();
}

int updateY(int pos, int val) {
    maxTree.update(pos, val);
    y[pos] = val;
    return solve();
}
#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...