Submission #62651

#TimeUsernameProblemLanguageResultExecution timeMemory
62651NnandiBuilding Bridges (CEOI17_building)C++14
100 / 100
1491 ms19776 KiB
#include <bits/stdc++.h>
#define INF 100000000000000000.0
using namespace std;

typedef long long ll;

struct Line {
    ll a, b; // Y = aX + b
    double kp, vp;
    Line() {}
    Line(ll aa, ll bb) {
        a = aa;
        b = bb;
    }
    const bool operator< (Line masik) const {
        if(a != masik.a) return a > masik.a;
        return b < masik.b;
    }
};

double cross(Line e, Line f) {
    return (double)(f.b - e.b) / (double)(e.a - f.a);
}

struct Burok {
    vector<Line> tab;
    bool ord;
    Burok() {
        tab.resize(0);
        ord = false;
    }
    void Add_Line(ll a, ll b) {
        ord = false;
        Line uj(a,b);
        tab.push_back(uj);
    }
    void Order() {
        ord = true;
        sort(tab.begin(),tab.end());
        if(tab.size()==1) return;
        vector<Line> ch(tab.size());
        ch[0] = tab[0];
        ll it = 1; while(it < tab.size() && ch[0].a == tab[it].a) { it++; };
        if(it >= tab.size())  {
            ch.resize(1);
            swap(tab,ch); return;
        }
        ch[1] = tab[it]; it++;
        ll hm = 1;
        for(;it<tab.size();it++) {
            if(tab[it].a == ch[hm].a) continue;
            bool kell = true;
            while(hm >= 1 && kell) {
                double ez = cross(ch[hm-1],tab[it]);
                double az = cross(ch[hm-1],ch[hm]);
                if(ez <= az) { //!!!!!!
                    hm--;
                }
                else {
                    kell = false;
                }
            }
            ch[hm+1] = tab[it]; hm++;
        }
        ch.resize(hm+1);
        swap(tab,ch);
        for(ll i=0;i<tab.size()-1;i++) {
            tab[i].vp = cross(tab[i],tab[i+1]);
            tab[i+1].kp = cross(tab[i+1],tab[i]);
        }
        tab[0].kp = -INF;
        tab[hm].vp = INF;
        return;
    }
    ll Get_Min_Value(ll x) {
        if(tab.size() == 0) return (ll)INF;
        if(!ord) {
            ll min_val(tab[0].a * x + tab[0].b);
            for(Line d:tab) {
                min_val = min(min_val,d.a * x + d.b);
            }
            return min_val;
        }
        else {
            ll b1 = 0;
            ll b2 = tab.size()-1;
            while(b1 < b2) {
                ll mid = (b1 + b2) / 2;
                if(tab[mid].kp <= (double)x && (double)x <=tab[mid].vp) {
                    b1 = mid;
                    b2 = mid;
                }
                else if(tab[mid].kp > (double)x) {
                    b2 = mid-1;
                }
                else {
                    b1 = mid+1;
                }
            }
            return x * tab[b1].a + tab[b1].b;
        }
    }
};

ll n;
const ll maxn = 100005;
ll h[maxn], w[maxn];

Burok data[400];
ll suf_sum[maxn];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n;
    for(ll i=0;i<n;i++) {
        cin>>h[i];
    }
    for(ll i=0;i<n;i++) {
        cin>>w[i];
    }
    suf_sum[n] = 0;
    for(ll i=n-1;i>=0;i--) {
        suf_sum[i] = suf_sum[i+1] + w[i];
    }
    ll g = (ll)sqrt(n);
    for(ll i=0;i<n;i++) {
        if(i == 0) {
            data[i/g].Add_Line(-2*h[i],h[i]*h[i] + suf_sum[i+1]);
        }
        else {
            ll min_pre_cost = (ll) INF;
            for(ll j=0;j<=i/g;j++) {
                min_pre_cost = min(min_pre_cost, data[j].Get_Min_Value(h[i]));
            }
            ll cost = min_pre_cost + h[i]*h[i] - suf_sum[i];
            if(i == n-1) {
                cout<<cost<<endl;
                return 0;
            }
            data[i/g].Add_Line(-2*h[i],cost + suf_sum[i+1] + h[i]*h[i]);
        }
        if((i+1) % g == 0) {
            data[i/g].Order();
        }
    }
    return 0;
}

Compilation message (stderr)

building.cpp: In member function 'void Burok::Order()':
building.cpp:43:29: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         ll it = 1; while(it < tab.size() && ch[0].a == tab[it].a) { it++; };
                          ~~~^~~~~~~~~~~~
building.cpp:44:15: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         if(it >= tab.size())  {
            ~~~^~~~~~~~~~~~~
building.cpp:50:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(;it<tab.size();it++) {
              ~~^~~~~~~~~~~
building.cpp:67:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(ll i=0;i<tab.size()-1;i++) {
                    ~^~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...