Submission #1344780

#TimeUsernameProblemLanguageResultExecution timeMemory
1344780Jakub_WozniakThe short shank; Redemption (BOI21_prison)C++20
10 / 100
642 ms355308 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;
int ansi = 0;
const int base = (1<<19);


struct node
{
    node* l = nullptr;
    node* r = nullptr;
    int sum = 0;

    node (int S){sum = S;}
    node (int S , node* L , node* R){sum = S  , l = L , r = R;}
};


vector <node*> roots; 

node* buduj(int l , int r)
{
    if(l == r)
    {
        return new node(0);
    }

    int s = (l+r)/2;
    return new node(0, buduj(l,s) , buduj(s+1,r));
}

node* U(int l , int r, int a ,int b , node *wsk)
{
    

    if(a <= l && r <= b)
    {
        return new node((r-l+1) ,wsk->l , wsk->r);
    }
    else if(r < a || b < l)
    {
        return wsk;
    }
    else
    {
        if(wsk->sum == (r-l+1) && wsk->l != nullptr)
        {
            (*(wsk->l)).sum = (r-l+1)/2; 
            (*(wsk->r)).sum = (r-l+1)/2; 
        
        }
        int s = (l+r)/2;
        node* L = U(l,s,a,b,wsk->l);
        node* R = U(s+1,r,a,b,wsk->r);
        return new node(L->sum+R->sum , L , R);
    }
}

int Q(int l , int r, int a ,int b , node* wsk)
{
    if(r < a || b < l)return 0;
    else if(wsk->sum == (r-l+1))
    {
        return min(r,b) - max(a,l)+1;
    }
    else if(a <= l && r <= b)
    {
        return wsk->sum;
    }
    else
    {
        int s = (l+r)/2;
        int res = 0;
        res += Q(l,s,a,b,wsk->l);
        res += Q(s+1,r,a,b,wsk->r);
        return res;
    }
}

int maxidrz[base*2];
void Up(int X , int val)
{
    X += base;
    maxidrz[X] = val;
    X /= 2;
    while(X)
    {
        maxidrz[X] = max(maxidrz[X*2] , maxidrz[2*X+1]);
        X /= 2;
    }
}

int Qp(int l , int r)
{
    if(r < l)return 0;
    int res =0;
    l += base;
    r += base;
    l--;
    r++;
    while(l/2 != r/2)
    {
        if((l&1) == 0)res = max(res,maxidrz[l+1]);
        if((r&1) == 1)res = max(res,maxidrz[r-1]);
        l /= 2;
        r /= 2;
    }
    return res;
}

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

    //cerr << i << ' ' << l << ' ' << r << '\n';

    dp[i][d] = maxn*10+124;
    int COST; // trzeba zupdatowac bo pomijam [i+1,l-1]
    ansi = 0;
    if(i <= l-2)ansi = Q(0,base-1,i,l-2,roots[(n-i+1)]);
    COST = ansi;

    //cerr << "   " << l << ' ' << COST << ' ' << i << ' ' << l-2 << ' ' << ' ' <<  t[i] << ' ' << n-i+1 << '\n';

    int Pop = 0;
    if(i <= l-2) Pop = Qp(i,l-2) - i - (l-2-i+1) + 1; // trzeba zupdatowac bo pomijam [i+1,l-1]
    
    int opt = -1;
    for(int j = max(l,i+1) ; j <= r ; j++)
    {
        Pop--;
        Pop = max(Pop,t[j-1]);
        if(Pop >= 0)COST++;

        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];
    }

    roots.push_back(buduj(0,base-1));
    for(int i = n ; i >= 1 ;i--)
    {
        //n <-> 1
        //n-1 <-> 2
        //...
        // n-i <-> i+1  ----> i  <-> n-i+1 
        //cerr << i << ' ' << t[i] <<  ": " << roots.size() << '\n';
        if(t[i] >= 0)
        {
            //cerr << "   " << i  << ' ' << i+t[i] << '\n';
            roots.push_back(U(0,base-1,i,min(i+t[i],base-1),roots.back()));
        }
        else 
        {
            roots.push_back((roots.back()));
        }
        //cerr << "   " << roots.back() -> sum << '\n';
        Up(i , t[i]+i);
    }

    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...