Submission #1277228

#TimeUsernameProblemLanguageResultExecution timeMemory
1277228andrei_iorgulescuHoliday (IOI14_holiday)C++20
30 / 100
28 ms4456 KiB
#include <bits/stdc++.h>

using namespace std;

using integer = int;
#define int long long

struct AIB///init(valorile posibile); update(val, fr) -> pune fr aparitii de val; query(k) -> suma celor mai mari k din structura
{
    map<int, int> mp;
    vector<int> rvalue;
    int n;
    vector<int> aib1, aib2;///aib1 -> cate <= i, aib2 -> suma rvalue a lor

    void init(vector<int> values)
    {
        mp.clear();
        rvalue.clear();
        n = 0;
        aib1.clear();
        aib2.clear();
        int psn = 0;
        sort(values.begin(), values.end());
        for (auto it : values)
        {
            if (!mp[it])
            {
                psn++;
                mp[it] = psn;
            }
        }
        n = psn;
        aib1.resize(n + 1);
        aib2.resize(n + 1);
        rvalue.resize(n + 1);
        for (auto it : values)
            rvalue[mp[it]] = it;
    }

    int query1(int pos)
    {
        int rr = 0;
        for (int i = pos; i > 0; i -= (i & -i))
            rr += aib1[i];
        return rr;
    }

    int query2(int pos)
    {
        int rr = 0;
        for (int i = pos; i > 0; i -= (i & -i))
            rr += aib2[i];
        return rr;
    }

    void update(int val, int fr)
    {
        val = mp[val];
        for (int i = val; i <= n; i += (i & -i))
        {
            aib1[i] += fr;
            aib2[i] += fr * rvalue[val];
        }
    }

    int query(int k)
    {
        if (query1(n) <= k)
            return query2(n);
        if (k <= 0)
            return 0;
        int sm_tot = query2(n);
        int df = query1(n) - k;
        int st = 0, pas = 1 << 18;
        while (pas != 0)
        {
            if (st + pas <= n and aib1[st + pas] <= df)
            {
                sm_tot -= aib2[st + pas];
                df -= aib1[st + pas];
                st += pas;
            }
            pas /= 2;
        }
        if (df != 0)
        {
            st++;
            sm_tot -= rvalue[st] * df;
        }
        return sm_tot;
    }
};

int n, s, d, a[100005];
AIB ds;
int opt[100005], rsp[100005];

void divide(int l, int r, int st, int dr)
{
    if (l > r)
        return;
    int mij = (l + r) / 2;
    for (int i = r; i >= mij; i--)
        ds.update(a[i], 1);
    int bst = -1, unde;
    for (int i = st; i <= dr; i++)
    {
        ds.update(a[i], 1);
        int cr = ds.query(d - 2 * (s - mij) - (i - s));
        if (cr > bst)
        {
            bst = cr;
            unde = i;
        }
    }
    opt[mij] = unde;
    rsp[mij] = bst;
    for (int i = dr; i >= st; i--)
        ds.update(a[i], -1);
    divide(l, mij - 1, st, opt[mij]);
    for (int i = mij; i <= r; i++)
        ds.update(a[i], -1);
    divide(mij + 1, r, opt[mij], dr);
}

int solve()
{
    vector<int> all_values;
    for (int i = 1; i <= n; i++)
        all_values.push_back(a[i]);
    AIB ds_caz1;
    ds_caz1.init(all_values);
    int ans = 0;
    for (int i = s; i <= n; i++)
    {
        ds_caz1.update(a[i], 1);
        ans = max(ans, ds_caz1.query(d - (i - s)));
    }
    ds.init(all_values);
    for (int i = 1; i <= n; i++)
        opt[i] = 0;
    if (s == 1 or s == n)
        return ans;
    ds.update(a[s], 1);
    divide(1, s - 1, s + 1, n);
    for (int i = 1; i < s; i++)
        ans = max(ans, rsp[i]);
    /*for (int l = 1; l < s; l++)
    {
        int bst = -1, ps;
        for (int i = l; i < s; i++)
            ds.update(a[i], 1);
        for (int i = s; i <= n; i++)
        {
            ds.update(a[i], 1);
            int cr = ds.query(d - (i - s) - 2 * (s - l));
            if (cr > bst)
                bst = cr, ps = i;
        }
        for (int i = l; i <= n; i++)
            ds.update(a[i], -1);
        opt[l] = ps;
        if (l > 1 and opt[l] < opt[l - 1])
            assert(false);
        ans = max(ans, bst);
    }*/
    return ans;
}

long long findMaxAttraction(integer N, integer Start, integer D, integer Attraction[])
{
    n = N;
    s = Start + 1;
    d = D;
    for (int i = 1; i <= n; i++)
        a[i] = Attraction[i - 1];
    int ans = solve();
    s = n - s + 1;
    reverse(a + 1, a + n + 1);
    ans = max(ans, solve());
    return ans;
}

/*
5 2 7
10 2 20 30 1
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...