Submission #1258653

#TimeUsernameProblemLanguageResultExecution timeMemory
1258653nerrrminNile (IOI24_nile)C++20
100 / 100
115 ms25784 KiB
#include "nile.h"
#define pb push_back
#include<bits/stdc++.h>
using namespace std;
const long long maxn = 3e5 + 10;
long long n, q;
long long w[maxn], a[maxn], b[maxn];

long long dp[maxn]; /// best match count
long long r[maxn];
long long ans;
long long pa[maxn], sz[maxn], res[maxn], gl[maxn], gr[maxn];
long long best_odd[maxn], best_even[maxn], bs[maxn];
long long other[maxn];

long long t[maxn * 4], val[maxn];

void build_tree(long long i, long long l, long long r)
{
    if(l == r)
    {
        t[i] = 1e17;
        return;
    }
    long long mid = (l + r)/2;
    build_tree(2*i, l, mid);
    build_tree(2*i+1, mid+1, r);
    t[i] = 1e17;
}

long long ql, qr;
long long query(long long i, long long l, long long r)
{
    if(qr < ql)return 1e17;
    if(qr < l || ql > r)return 1e17;
    if(ql <= l && r <= qr)return t[i];
    long long mid = (l + r)/2;
    return min(query(2*i, l, mid), query(2*i+1, mid+1, r));
}

long long upos;
void update(long long i, long long l, long long r)
{
    if(l == r)
    {
       // cout << "updated " << val[l] << endl;
        t[i] = val[l];
        return;
    }
    long long mid = (l + r)/2;
    if(upos <= mid)update(2*i, l, mid);
    else update(2*i+1, mid+1, r);
    t[i] = min(t[2*i], t[2*i+1]);

}
long long find_leader(long long i)
{
    if(pa[i] == i)return i;
    return (pa[i] = find_leader(pa[i]));
}
void change(int i, int index)
{long long nowans = res[i];
ans -= nowans;
    if(index > gl[i] && index < gr[i])
    {
        other[i] = min(other[i], val[index]);
        res[i] = bs[i];
        long long cut = min(best_odd[i],  other[i]);
        if(sz[i] & 1)res[i] += cut;
    }
    ans += res[i];
}
void unite(long long i, long long j)
{
    i = find_leader(i);
    j = find_leader(j);
    if(i == j)return;
    if(i > j)swap(i, j);

    ans -= res[i];
    ans -= res[j];
    long long lft = sz[i];
    sz[i] += sz[j];
    pa[j] = i;
    gl[i] = min(gl[i], gl[j]);
    gr[i] = max(gr[i], gr[j]);


   // cout << gl[i] << ' ' << gr[i] << endl;
    if(lft & 1)
    {
        best_even[i] = min(best_even[i], best_odd[j]);
        best_odd[i] = min(best_odd[i], best_even[j]);
    }
    else
    {
        best_even[i] = min(best_even[i], best_even[j]);
        best_odd[i] = min(best_odd[i], best_odd[j]);
    }
    bs[i] += bs[j];
    res[i] = bs[i];
    long long cut = best_odd[i];
    ql = gl[i] + 1;
    qr = gr[i] - 1;
    long long newcut = query(1, 0, n-1);
    other[i] = newcut;
    cut = min(cut, newcut);
    if(sz[i] & 1)res[i] += cut;//(sz[i] % 2);

    ans += res[i];

}
vector < pair < long long, long long > > u;
void solve()
{
   vector < pair < long long, long long > > g;
   vector < pair < long long, long long > > v;
   for (long long i = 1; i < n; ++ i)
   {
       long long d = w[i] - w[i-1];
       g.push_back(make_pair(d, i-1));
   }
   for (long long i = 1; i < n-1; ++ i)
   {
       long long con = w[i+1] - w[i-1];
       v.pb(make_pair(con, i));
   }
   sort(g.begin(), g.end());
   sort(v.begin(), v.end());
   long long i = 0, j = 0;
    for (auto &[dif, pos]: u)
    {
        while(j < v.size() && v[j].first <= dif)
        {
            upos = v[j].second;
            update(1, 0, n-1);
            int lead = find_leader(upos);
            change(lead, upos);
            j ++;
        }
        while(i < g.size() && g[i].first <= dif)
        {
            long long posx = g[i].second;
            long long posy = posx + 1;
            unite(posx, posy);
            i ++;
        }
        r[pos] = ans;
    }
}

struct p
{
    long long w, a, b;
    p() {};
    p(long long _w, long long _a, long long _b)
    {
        w = _w;
        a = _a;
        b = _b;
    }
};

bool cmp(p p1, p p2)
{
    return (p1.w < p2.w);
}
std::vector<long long> calculate_costs(std::vector<int> W, std::vector<int> A,
                                       std::vector<int> B, std::vector<int> E)
{
    n = W.size();
    for (long long i = 0; i < n; ++ i)
        w[i] = W[i];
    for (long long i = 0; i < n; ++ i)
        a[i] = A[i];
    for (long long i = 0; i < n; ++ i)
        b[i] = B[i];
    vector < p > g;
    for (long long i = 0; i < n; ++ i)
        g.pb(p(w[i], a[i], b[i]));
    sort(g.begin(), g.end(), cmp);
    long long i = 0;
    for (auto &[ww, aa, bb]: g)
    {

        w[i] = ww;
        a[i] = aa;
        b[i] = bb;
        i ++;
    }
    build_tree(1, 0, n-1);
    for (long long i = 0; i < n; ++ i)
    {
        val[i] = a[i] - b[i];
        pa[i] = i;
        sz[i] = 1;
        res[i] = a[i];
        bs[i] = b[i];
        other[i] = 1e17;
        best_odd[i] = a[i] - b[i];
        best_even[i] = 1e17;
        gl[i] = i;
        gr[i] = i;
        ans += a[i];
    }
    q = (long long)E.size();
    vector < long long > result;
    for (long long i = 0; i < E.size(); ++ i)
    {
        u.pb(make_pair(E[i], i));
    }
    sort(u.begin(), u.end());
    solve();

    for (long long i = 0; i < q; ++ i)
        result.pb(r[i]);
    return result;
}
#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...