Submission #1344191

#TimeUsernameProblemLanguageResultExecution timeMemory
1344191Jakub_WozniakThe short shank; Redemption (BOI21_prison)C++20
15 / 100
2098 ms135700 KiB
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define st first
#define nd second
const ll maxn = 500000+912;
vector<vector<int>> dp;
int t[maxn];
int n , D , T;

const int base = (1<<19);
vector <pii> drz[base*2]; // {czas , wartosc w danym czasie}
int aktTIME = 1;

void nowy(int pos , int T , int w)
{
    if(drz[pos].back().nd >= w)return ;
    drz[pos].push_back({T,w});
}

void U(int l , int r, int a ,int b , int pos)
{
    if((drz[pos].back()).nd == r-l+1 && pos < base) // wszystkie zapalone
    {
        nowy(pos*2,drz[pos].back().st , drz[pos].back().nd/2);
        nowy(pos*2+1,drz[pos].back().st , drz[pos].back().nd/2);
    }

    if(a <= l && r <= b)
    {
        nowy(pos,aktTIME , r-l+1);
    }
    else if(r < a || b < l)return ;
    else
    {
        int s = (l+r)/2;
        U(l,s,a,b,pos*2);
        U(s+1,r,a,b,pos*2+1);
        int w = drz[pos*2].back().nd + drz[pos*2+1].back().nd;
        nowy(pos,aktTIME,w);
    }
}

int ansi = 0;
void Q(int l , int r, int a ,int b , int pos , int TIM)
{
    if((drz[pos].back()).nd == r-l+1 && pos < base) // wszystkie zapalone
    {
        nowy(pos*2,drz[pos].back().st , drz[pos].back().nd/2);
        nowy(pos*2+1,drz[pos].back().st , drz[pos].back().nd/2);
    }

    if(a <= l && r <= b)
    {
        auto it = lower_bound(drz[pos].begin() , drz[pos].end() , (pii){TIM+1,-1});
        it--;   
        ansi += (*it).nd;
    }
    else if(r < a || b < l)return ;
    else
    {
        int s = (l+r)/2;
        Q(l,s,a,b,pos*2 , TIM);
        Q(s+1,r,a,b,pos*2+1, TIM);
    }
}


void rek(int i1 , int i2 , int l , int r , int d)
{
    if(i2 < i1)return ;
    int i = (i1+i2)/2;

    dp[i][d] = maxn*10+124;
    int COST = 0; // trzeba zupdatowac bo pomijam [i+1,l-1]
    int Pop = 0; // trzeba zupdatowac bo pomijam [i+1,l-1]
    
    int opt = -1;
    for(int j = max(l,i+1) ; j <= r ; j++)
    {
        ansi = 0;
        Q(0,base-1,i,j-1,1,(n-i+1));
        COST = ansi;
        if(dp[i][d] > dp[j][d-1] + COST)opt = j;
        dp[i][d] = min(dp[i][d] , dp[j][d-1] + COST);
    }
    rek(i1,i-1,l,opt,d);
    rek(i+1,i2,opt,r,d);
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    cin >> n >> D >> T;
    for(int i = 1; i<= n ;i++)
    {
        cin >> t[i];
        t[i] = T-t[i];
    }
    cerr << '\n';

    for(int i = 0 ; i < base*2 ; i++)drz[i].push_back({0,0});
    for(int i = n ; i >= 1 ;i--)
    {
        //n <-> 1
        //n-1 <-> 2
        //...
        // n-i <-> i+1  ----> i  <-> n-i+1 
        if(t[i] >= 0)U(0,base-1,i,min(i+t[i],base-1),1);
        aktTIME++;
    }

    dp.resize(n+5);
    for(int i = 0 ; i <= n+3 ; i++)dp[i].resize(D+3);

    for(int i = 1; i <= n ; i++)dp[i][0] = maxn*123+15;
    for(int d = 1 ; d <= D+1 ; d++)
    {
        rek(1,n,1,n+1,d);
    }

    cout << dp[1][D+1] << '\n';

    return 0;
}
#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...