Submission #426399

#TimeUsernameProblemLanguageResultExecution timeMemory
426399timmyfengShortcut (IOI16_shortcut)C++17
100 / 100
1857 ms105504 KiB
#include <bits/stdc++.h>
using namespace std;
 
const int N = 1000001;
 
long long sum_s[N], diff_s[N], sum_d[N], diff_d[N];
long long prefix_sum[N], prefix_diff[N];
long long sum[N], diff[N], x[N];
int order[N], n;
 
long long find_shortcut(int n, vector<int> l, vector<int> d, int c) {
    ::n = n;
 
    for (int i = 0; i < n - 1; ++i) {
        x[i + 1] = x[i] + l[i];
    }
 
    for (int i = 0; i < n; ++i) {
        sum[i] = x[i] + d[i];
        diff[i] = x[i] - d[i];
    }
 
    sort(d.rbegin(), d.rend());
 
    iota(order, order + n, 0);
    sort(order, order + n, [&](int a, int b) {
        return diff[a] < diff[b];
    });
 
    for (int i = 0; i < n; ++i) {
        sum_d[i] = sum[order[i]];
        diff_d[i] = diff[order[i]];
    }
 
    iota(order, order + n, 0);
    sort(order, order + n, [&](int a, int b) {
        return sum[a] < sum[b];
    });
 
    for (int i = 0; i < n; ++i) {
        sum_s[i] = sum[order[i]];
        diff_s[i] = diff[order[i]];
    }

    prefix_sum[0] = LLONG_MIN, prefix_diff[0] = LLONG_MAX;
    for (int i = 0; i < n; ++i) {
        prefix_sum[i + 1] = max(prefix_sum[i], sum_d[i]);
        prefix_diff[i + 1] = min(prefix_diff[i], diff_d[i]);
    }
 
    long long low = d[0] + d[1], high = sum_s[n - 1] - diff_d[0];
    while (low < high) {
        long long mid = (low + high) / 2;
 
        long long min_sum = LLONG_MIN, max_sum = LLONG_MAX;
        long long min_diff = LLONG_MIN, max_diff = LLONG_MAX;
 
        for (int i = 0, j = 0; j < n; ++j) {
            while (i < n && sum_s[j] - diff_d[i] > mid) {
                ++i;
            }
 
            if (sum_s[j] - diff_s[j] > mid) {
                int y = order[j];
                for (int x = 0; x < y; ++x) {
                    if (sum[y] - diff[x] > mid) {
                        min_sum = max(min_sum, -mid + c + sum[y] + sum[x]);
                        max_sum = min(max_sum, mid - c + diff[y] + diff[x]);
                        min_diff = max(min_diff, -mid + c + sum[y] - diff[x]);
                        max_diff = min(max_diff, mid - c + diff[y] - sum[x]);
                    }
                }
            } else if (i > 0) {
                min_sum = max(min_sum, -mid + c + sum_s[j] + prefix_sum[i]);
                max_sum = min(max_sum, mid - c + diff_s[j] + prefix_diff[i]);
                min_diff = max(min_diff, -mid + c + sum_s[j] - prefix_diff[i]);
                max_diff = min(max_diff, mid - c + diff_s[j] - prefix_sum[i]);
            }
        }
 
        bool ok = false;
        int l1 = n - 1, l2 = 0, r1 = n - 1, r2 = 0;
        for (int i = 0; i < n; ++i) {
            while (l1 >= 0 && x[i] + x[l1] >= min_sum) {
                --l1;
            }
            while (r1 >= 0 && x[i] + x[r1] > max_sum) {
                --r1;
            }
            while (l2 < n && x[i] - x[l2] > max_diff) {
                ++l2;
            }
            while (r2 < n && x[i] - x[r2] >= min_diff) {
                ++r2;
            }
            ok |= max(l1 + 1, l2) < min(r1 + 1, r2);
        }
 
        if (ok) {
            high = mid;
        } else {
            low = mid + 1;
        }
    }
 
    return low;
}
#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...