Submission #1347289

#TimeUsernameProblemLanguageResultExecution timeMemory
1347289penguin133Teleporter 2 (JOI26_teleporter)C++20
100 / 100
2061 ms26396 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//fk const time bro
//#define int long long
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
int n, m, k;
int a[100005][3];
vector <pair <int, int> > to[100005];

pair <ll, int> t[1<<19];
ll lazy[1<<19];

void build(int v, int tl, int tr){
	if(tl == tr)t[v] = {0, 0};
	else {
		build(v<<1, tl, (tl+tr)>>1);
		build(v<<1|1, ((tl+tr)>>1) + 1, tr);
		t[v] = min(t[v<<1], t[v<<1|1]);
	}
    lazy[v] = 0;
}

inline void push(int v, int tl, int tr) {
    int tm = (tl + tr) >> 1;
    t[v<<1].first += lazy[v];
    lazy[v<<1] += lazy[v];
    t[(v<<1)+1].first += lazy[v];
    lazy[(v<<1)+1] += lazy[v];
    lazy[v] = 0;
}

inline void update(int v, int tl, int tr, int l, int r, ll addend) {
    if (l > r) 
        return;
    push(v, tl, tr);
    if (l == tl && tr == r) {
        t[v].first += addend;
        lazy[v] += addend;
    } else {
        push(v, tl, tr);
        int tm = (tl + tr) >> 1;
	    update(v<<1, tl, tm, l, min(r, tm), addend);
	    update((v<<1)+1, tm+1, tr, max(l, tm+1), r, addend);
        t[v] = min(t[v<<1], t[(v<<1)+1]);
    }
}

inline void upos (int v, int tl, int tr, int p, int V) {
    if (p < tl || p > tr) return;
    push(v, tl, tr);
    if (tl == tr) {
        t[v].second = V;
    }
    else {
        push(v, tl, tr);
        int tm = (tl + tr) >> 1;
	    upos(v<<1, tl, tm, p, V);
	    upos((v<<1)+1, tm+1, tr, p, V);
        t[v] = min(t[v<<1], t[(v<<1)+1]);
    }
}

inline pair <ll, int> query(int v, int tl, int tr, int l, int r) {
    if (l > r)
        return {1e18, 1e9};
    if (l == tl && tr == r)
        return t[v];
    push(v, tl, tr);
    int tm = (tl + tr) >> 1;
    return min(query(v<<1, tl, tm, l, min(r, tm)),
               query((v<<1)+1, tm+1, tr, max(l, tm+1), r));
}

int32_t main () {
    ios::sync_with_stdio(0); cin.tie(0);
    cin >> n >> m >> k;
    ll tot = 0;
    for (int i = 1; i <= m; i++) {
        cin >> a[i][0] >> a[i][1] >> a[i][2];
        to[a[i][1]].push_back({a[i][0], a[i][2]});
        tot += a[i][2];
    }
    if (k == 1) {
        vector < vector <ll> > dp(n + 1, vector <ll>(k + 3, 0));
        dp[0][0] = 0;
        for (int i = 1; i <= n; i++) dp[i][0] = 1e18;
        for (int i = 1; i <= k + 1; i++) {
            build(1, 0, n);
            for (int j = 0; j <= n; j++) {
                update(1, 0, n, j, j, dp[j][i - 1]);
            }
            for (int j = 1; j <= n; j++) {
                dp[j][i] = 1e18;
                /*
                ll c = 0;
                for (int l = j - 1; l >= 0; l--) {
                    for (auto [a, b] : fr[l + 1]) if (a <= j) c += b;
                    //for (int x = 1; x <= m; x++) if (a[x][0] > l && a[x][1] <= j) c += a[x][2];
                    dp[j][i] = min(dp[j][i], dp[l][i - 1] + c);
                }
                */
                for (auto [a, b] : to[j]) update(1, 0, n, 0, a - 1, b);
                dp[j][i] = query(1, 0, n, 0, j - 1).first;
            }
        }
        cout << dp[n][k + 1];
        return 0;
    }
    //let dp[i][j] = min. cost such that there are j disjoint segments in [1, i], and  there are no active teleporters that start and end at the same segment.
    
    k = min(k, n);
    ll lo = 0, hi = tot / (k + 1) + 1, ans = hi, T = 1e18;
    vector < pair <ll, int> > dp(n + 1);
    while (lo <= hi) {
        ll mid = (lo + hi) >> 1;
        //build(1, 0, n);
        for (int j = 0; j <= n * 4 + 5; j++) t[j] = {0, 0}, lazy[j] = 0;
        dp[0] = {0, 0};
        for (int i = 1; i <= n; i++) {
            //for (auto [a, b] : to[i]) root->upd(0, a - 1, b);
            for (auto &[a, b] : to[i]) update(1, 0, n, 0, a - 1, b);
            //auto res = root->qry(0, i - 1);
            auto res = query(1, 0, n, 0, i - 1);
            dp[i] = {res.first + mid, res.second + 1};
            //root->upd(i, i, dp[i].first);
            //root->upos(i, dp[i].second);
            update(1, 0, n, i, i, dp[i].first);
            upos(1, 0, n, i, dp[i].second);
        }
        if (dp[n].second <= k + 1) ans = mid, hi = mid - 1;
        else lo = mid + 1;
    }
    //cout << ans << '\n';
    //root = new node(0, n);
    
    for (int j = 0; j <= n * 4 + 5; j++) t[j] = {0, 0}, lazy[j] = 0;
    dp[0] = {0, 0};
    for (int i = 1; i <= n; i++) {
        //for (auto [a, b] : to[i]) root->upd(0, a - 1, b);
        for (auto &[a, b] : to[i]) update(1, 0, n, 0, a - 1, b);
        //auto res = root->qry(0, i - 1);
        auto res = query(1, 0, n, 0, i - 1);
        dp[i] = {res.first + ans, res.second + 1};
        //root->upd(i, i, dp[i].first);
        //root->upos(i, dp[i].second);
        update(1, 0, n, i, i, dp[i].first);
        upos(1, 0, n, i, dp[i].second);
    }
    //cout << dp[n].first << ' ' << dp[n].second << '\n';
    cout << dp[n].first - (k + 1) * 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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...