Submission #1191835

#TimeUsernameProblemLanguageResultExecution timeMemory
1191835Joon_YorigamiHorses (IOI15_horses)C++20
100 / 100
732 ms49176 KiB
#include "horses.h"
#include <bits/stdc++.h>
using namespace std;
#define ll long long

static const int MAXN = 500000;
static const int MOD  = 1000000007;

int N;
int Xarr[MAXN], Yarr[MAXN];
int prodSeg[4*MAXN], capSeg[4*MAXN];
int ySeg[4*MAXN];
int bestSeg[4*MAXN];
set<int> growths;

void buildProd(int node, int l, int r)
{
    if (l == r)
    {
        prodSeg[node] = Xarr[l] % MOD;
        capSeg[node]  = min(Xarr[l], 1000000000);
    }
    else
    {
        int mid = (l + r) >> 1;
        buildProd(node*2,   l,   mid);
        buildProd(node*2+1, mid+1, r);
        prodSeg[node] = int(1LL * prodSeg[node*2] * prodSeg[node*2+1] % MOD);
        capSeg[node]  = int(min(1000000000LL, 1LL * capSeg[node*2] * capSeg[node*2+1]));
    }
}

int queryProd(int seg[], int capArr[], int ql, int qr, bool capFlag, int node_l, int node_r, int node)
{
    if (qr < node_l || node_r < ql) return 1;
    if (ql <= node_l && node_r <= qr)
    {
        return capFlag ? capArr[node] : seg[node];
    }
    int mid = (node_l + node_r) >> 1;
    ll left  = queryProd(seg, capArr, ql, qr, capFlag, node_l,   mid, node*2);
    ll right = queryProd(seg, capArr, ql, qr, capFlag, mid+1, node_r, node*2+1);
    if (capFlag) return int(min(1000000000LL, left * right));
    return int((left * right) % MOD);
}

void updateProd(int seg[], int capArr[], int pos, int val, int node_l, int node_r, int node)
{
    if (node_l == node_r)
    {
        seg[node]    = val % MOD;
        capArr[node] = min(val, 1000000000);
    }
    else
    {
        int mid = (node_l + node_r) >> 1;
        if (pos <= mid)
            updateProd(seg, capArr, pos, val, node_l,   mid, node*2);
        else
            updateProd(seg, capArr, pos, val, mid+1, node_r, node*2+1);
        seg[node]    = int(1LL * seg[node*2] * seg[node*2+1] % MOD);
        capArr[node] = int(min(1000000000LL, 1LL * capArr[node*2] * capArr[node*2+1]));
    }
}

void buildY(int node, int l, int r)
{
    if (l == r)
    {
        ySeg[node] = l;
    }
    else
    {
        int mid = (l + r) >> 1;
        buildY(node*2,   l,   mid);
        buildY(node*2+1, mid+1, r);
        int a = ySeg[node*2], b = ySeg[node*2+1];
        ySeg[node] = (Yarr[a] >= Yarr[b] ? a : b);
    }
}

void updateYseg(int node, int l, int r, int pos)
{
    if (l == r) return;
    int mid = (l + r) >> 1;
    if (pos <= mid)
    {
        updateYseg(node*2,   l,   mid, pos);
    }
    else
    {
        updateYseg(node*2+1, mid+1, r, pos);
    }
    int a = ySeg[node*2], b = ySeg[node*2+1];
    ySeg[node] = (Yarr[a] >= Yarr[b] ? a : b);
}

void buildBest(int node, int l, int r)
{
    if (l == r)
    {
        bestSeg[node] = l;
    }
    else
    {
        int mid = (l + r) >> 1;
        buildBest(node*2,   l,   mid);
        buildBest(node*2+1, mid+1, r);
        int L = bestSeg[node*2], R = bestSeg[node*2+1];
        ll cap  = queryProd(prodSeg, capSeg, L+1, R, true, 0, N-1, 1);
        ll need = (Yarr[L] + Yarr[R] - 1LL) / Yarr[R];
        bestSeg[node] = (cap >= need ? R : L);
    }
}

void updateBest(int node, int l, int r, int pos)
{
    if (l == r) return;
    int mid = (l + r) >> 1;
    if (pos <= mid)
    {
        updateBest(node*2,   l,   mid, pos);
    }
    else
    {
        updateBest(node*2+1, mid+1, r, pos);
    }
    int L = bestSeg[node*2], R = bestSeg[node*2+1];
    ll cap  = queryProd(prodSeg, capSeg, L+1, R, true, 0, N-1, 1);
    ll need = (Yarr[L] + Yarr[R] - 1LL) / Yarr[R];
    bestSeg[node] = (cap >= need ? R : L);
}

int init(int NN, int X[], int Y[])
{
    N = NN;
    for (int i = 0; i < N; i++)
    {
        Xarr[i] = X[i];
        Yarr[i] = Y[i];
        if (Xarr[i] != 1) growths.insert(i);
    }
    growths.insert(0);
    buildProd(1, 0, N-1);
    buildY(1, 0, N-1);
    buildBest(1, 0, N-1);
    int idx = bestSeg[1];
    return int(1LL * queryProd(prodSeg, capSeg, 0, idx, false, 0, N-1, 1) * Yarr[idx] % MOD);
}

int updateX(int pos, int val)
{
    Xarr[pos] = val;
    if (val == 1 && pos != 0) growths.erase(pos);
    else growths.insert(pos);
    updateProd(prodSeg, capSeg, pos, val, 0, N-1, 1);
    updateBest(1, 0, N-1, pos);
    int idx = bestSeg[1];
    return int(1LL * queryProd(prodSeg, capSeg, 0, idx, false, 0, N-1, 1) * Yarr[idx] % MOD);
}

int updateY(int pos, int val)
{
    Yarr[pos] = val;
    updateYseg(1, 0, N-1, pos);
    updateBest(1, 0, N-1, pos);
    int idx = bestSeg[1];
    return int(1LL * queryProd(prodSeg, capSeg, 0, idx, false, 0, N-1, 1) * Yarr[idx] % MOD);
}
#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...