Submission #489990

#TimeUsernameProblemLanguageResultExecution timeMemory
489990blueTreatment Project (JOI20_treatment)C++17
0 / 100
529 ms301080 KiB
#include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
#include <stack>
#include <set>
using namespace std;

using ll = long long;
using pll = pair<ll, ll>;
using vpll = vector<pll>;
using vi = vector<int>;
using vll = vector<ll>;

struct project
{
    int T;
    int L;
    int R;
    int C;
    int I;
};



vector<project> P;

const int maxM = 100'000;
vi query_ans;

vi visited(maxM, 0);

const ll INF = 1'000'000'000'000'000'000LL;

vll dp(maxM, INF);

struct pos
{
    int i;
};

bool operator < (pos A, pos B)
{
    if(dp[A.i] == dp[B.i]) return A.i < B.i;
    else return dp[A.i] < dp[B.i];
}



struct segtree
{
    int l;
    int r;
    stack<pair<int, int>> u;
    stack<pair<int, int> >d;

    segtree* left = NULL;
    segtree* right = NULL;

    segtree()
    {
        ;
    }

    segtree(int L, int R)
    {
        l = L;
        r = R;
        if(l == r) return;

        int m = (l+r)/2;
        left = new segtree(l, m);
        right = new segtree(m+1, r);
    }

    void addU(int I, ll Pr, ll val)
    {
        u.push({Pr, val});
        if(l != r)
        {
            if(I <= (l+r)/2) left->addU(I, Pr, val);
            else right->addU(I, Pr, val);
        }
    }

    void getU(int L, int R, ll mxv)
    {
        if(R < l || r < L) return;
        else if(L <= l && r <= R)
        {
            while(1)
            {
                if(u.empty()) break;
                if(u.top().second > mxv) break;
                if(!visited[u.top().first])
                {
                    query_ans.push_back(u.top().first);
                    visited[u.top().first] = 1;
                }
                u.pop();
            }
        }
        else
        {
            left->getU(L, R, mxv);
            right->getU(L, R, mxv);
        }
    }










    void addD(int I, ll Pr, ll val)
    {
        d.push({Pr, val});
        if(l != r)
        {
            if(I <= (l+r)/2) left->addD(I, Pr, val);
            else right->addD(I, Pr, val);
        }
    }

    void getD(int L, int R, ll mxv)
    {
        if(R < l || r < L) return;
        else if(L <= l && r <= R)
        {
            while(1)
            {
                if(d.empty()) break;
                if(d.top().second > mxv) break;
                if(!visited[d.top().first])
                {
                    query_ans.push_back(d.top().first);
                    visited[d.top().first] = 1;
                }
                d.pop();
            }
        }
        else
        {
            left->getD(L, R, mxv);
            right->getD(L, R, mxv);
        }
    }
};

int main()
{
    int N, M;
    cin >> N >> M;

  M = min(M, 100000);

    P = vector<project>(M);
    for(int i = 0; i < M; i++) cin >> P[i].T >> P[i].L >> P[i].R >> P[i].C;

    sort(P.begin(), P.end(), [] (project x, project y)
    {
        return x.T < y.T;
    });

    for(int i = 0; i < M; i++) P[i].I = i;


        segtree S(0, M-1);
    sort(P.begin(), P.end(), [] (project x, project y)
    {
        return x.L + x.T > y.L + y.T;
    });

    for(int i = 0; i < M; i++)
        S.addU(P[i].I, P[i].I, P[i].L + P[i].T);

    sort(P.begin(), P.end(), [] (project x, project y)
    {
        return x.L - x.T <= y.L - y.T;
    });

    for(int i = 0; i < M; i++)
        S.addD(P[i].I, P[i].I, P[i].L - P[i].T);



    sort(P.begin(), P.end(), [] (project x, project y)
    {
        return x.I < y.I;
    });

    for(int i = 0; i < M; i++)
    {
        if(P[i].L == 1)
        {
            dp[i] = P[i].C;
            visited[i] = 1;
        }
    }



    set<pos> tbv;
    for(int i = 0; i < M; i++) tbv.insert(pos{i});

    while(!tbv.empty())
    {
        int u = tbv.begin()->i;
        tbv.erase(tbv.begin());
        // cerr << "visiting " << u << ' ' << P[u].L << ' ' << P[u].R <<  '\n';


        if(!visited[u]) break;


        query_ans.clear();
        S.getU(u+1, M-1, P[u].R + P[u].T + 1);
        S.getD(0, u-1, P[u].R - P[u].T + 1);

        for(int v: query_ans)
        {
            // cerr << u << " -> " << v << '\n';
            if(P[v].L <= P[u].R + 1 - abs(P[u].T - P[v].T))
            {
                if(dp[v] > dp[u] + P[v].C)
                {

                    tbv.erase(pos{v});
                    dp[v] = dp[u] + P[v].C;
                    tbv.insert(pos{v});
                }
            }
        }

    }

    ll final_ans = INF;
    for(int i = 0; i < M; i++)
        if(P[i].R == N)
            final_ans = min(final_ans, dp[i]);

    if(final_ans >= INF) final_ans = -1;

    cout << final_ans << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...