Submission #1258579

#TimeUsernameProblemLanguageResultExecution timeMemory
1258579Noname_1900Growing Vegetables is Fun 4 (JOI21_ho_t1)C++20
100 / 100
15 ms6532 KiB
#include<bits/stdc++.h>
using namespace std;
const int NMAX = 200000+1;
#define int long long
const int INFINI = 1e17;
int N;
int hauteur[NMAX];
int chang[NMAX];
//int proGrand[2][NMAX]
/*
//lazy
int arbre[NMAX*3];
pair<int, int> debFin[NMAX*3];
int push[NMAX*3];
int construire(int noeud, int deb, int fin)
{
    push[noeud] = 0;
    debFin[noeud] = {deb, fin};
    if(deb == fin-1)
    {
        return arbre[noeud] = chang[noeud];
    }
    int mil = deb+fin;
    mil/=2;
    return arbre[noeud] = min(construire(noeud*2, deb, mil), construire(noeud*2+1, mil, fin));
}
void pousser(int noeud)
{
    int ajout = push[noeud];
    push[noeud] = 0;
    arbre[noeud] += ajout;
    if(debFin[noeud].first != debFin[noeud].second-1)
    {
        push[noeud*2] += ajout;
        push[noeud*2+1]+= ajout;
    }
}
int trouverMin(int noeud, int deb, int fin)
{
    pousser(noeud);
    if((debFin[noeud].first <= deb)&&(debFin[noeud].second >= fin)) return arbre[noeud];
    if((debFin[noeud].first >= fin) || (debFin[noeud].second <= deb))   return INFINI;
    return min(trouverMin(noeud*2, deb, fin), trouverMin(noeud*2+1, deb, fin));
}
int maj(int noeud, int deb, int fin, int ajout)
{
    pousser(noeud);
    if((debFin[noeud].first <= deb)&&(debFin[noeud].second >= fin)){
        push[noeud] += ajout;
        pousser(noeud);
        return arbre[noeud];
    } 
    if((debFin[noeud].first >= fin) || (debFin[noeud].second <= deb))   return arbre[noeud];
    return arbre[noeud] = min(maj(noeud*2, deb, fin, ajout), maj(noeud*2+1, deb, fin, ajout));
}/** */
//map<int, vector<int>> ordre;
void initChang()
{
    int milieu = 1;
    int hActu = -1;
    if(milieu != 1)
    {
        for(int i = 1; i < milieu; i++)
        {
            chang[i] = max(hActu+1, hauteur[i]) - hauteur[i];
            hActu = max(hActu+1, hauteur[i]);
        }
    }
    
    hActu = -1;
    if(milieu != N)
    {
        for(int i = N; i > milieu; i--)
        {
            chang[i] = max(hActu+1, hauteur[i]) - hauteur[i];
            hActu = max(hActu+1, hauteur[i]);
        }
    }
    if(milieu == 1)
    {
        chang[milieu] = max(hauteur[milieu], hauteur[milieu+1]+chang[milieu+1]+1) - hauteur[milieu];
    }
    else if(milieu == N)
    {
        chang[milieu] = max(hauteur[milieu], hauteur[milieu-1]+chang[milieu-1]+1) - hauteur[milieu];
    }
    else
    {
        chang[milieu] =  max(hauteur[milieu], max(hauteur[milieu-1]+chang[milieu-1], hauteur[milieu+1]+chang[milieu+1])+1) - hauteur[milieu];
    }
}
int resG[NMAX];
int resD[NMAX];
int augmentationG[NMAX+1];
int augmentationD[NMAX+1];
int ancAugG, ancAugD;
void initRes()
{
    int milieu = 1;
    for(int i = 1; i <= 1; i++)
    {
        resG[i] = resG[i-1];
        if(chang[i] >= chang[i-1])
        {
            resG[i] += chang[i] - chang[i-1];
        }
     //   augmentationG[i] = chang[i];
        
            
    }
    for(int i = N; i >= 1; i--)
    {
        resD[i] = resD[i+1];
        if(chang[i] >= chang[i+1])
        {
            resD[i] += chang[i] - chang[i+1];
        }
     //   augmentationD[i] = chang[i];
        //cout << i << " " << resD << endl;
    }
}
void updateChang(int iMilieuNouv)
{
    if(iMilieuNouv == 2)
    {
        chang[iMilieuNouv-1] = 0;
    }
    else
        chang[iMilieuNouv-1] = max(hauteur[iMilieuNouv-2]+chang[iMilieuNouv-2] +1, hauteur[iMilieuNouv-1]) - hauteur[iMilieuNouv-1];

    if(iMilieuNouv == N)
    {
        chang[iMilieuNouv] = max(hauteur[iMilieuNouv], hauteur[iMilieuNouv-1]+chang[iMilieuNouv-1]+1) - hauteur[iMilieuNouv];
    }
    else
    {
        chang[iMilieuNouv] =  max(hauteur[iMilieuNouv], max(hauteur[iMilieuNouv-1]+chang[iMilieuNouv-1], hauteur[iMilieuNouv+1]+chang[iMilieuNouv+1])+1) - hauteur[iMilieuNouv];
    }
    
}
void updateRes(int imilieu)
{
    //TO DO
    if(imilieu > N) return;
    if(imilieu == 2)
    {
        resG[1] = 0;
       // augmentationG[1] = 0;
    }
  //  for(int i = 1; i <= N; i++) cout << chang[i] << " ";
   // cout << endl;
    //augmentationG[imilieu-1] = chang[imilieu-1];
    for(int i = max((long long)2, imilieu-1); i <= imilieu; i++)
    {
        resG[i] = resG[i-1];
        if(chang[i] >= chang[i-1])
        {
            resG[i] += chang[i] - chang[i-1];
          //  cout << i << " " << resG[i] << ' ' << chang[i-1] << " " << chang[i] << endl;
        }
       // augmentationG[i] = chang[i];
    }//*
    if(imilieu == N)    resD[N] = chang[N];
    else
    {
        resD[imilieu] = resD[imilieu+1];
        if(chang[imilieu] >= chang[imilieu+1])
        {
            resD[imilieu] += chang[imilieu] - chang[imilieu+1];
        }
        ///cout << imilieu << " " << resD[imilieu+1] << " " << chang[imilieu] << " " << chang[imilieu+1] << endl;
    }
   // cout << "update " << imilieu << " resG : " << resG[imilieu] << " | rssD : " << resD[imilieu] <<endl;
}
int trouvercoutmin(int milieu)
{
    //etape Montee
    
    //construire(1, 0, N);
  //  cout << milieu << endl;
  //  for(int i = 0; i < N; i++)  cout << chang[i] << " ";
  //  cout << endl;
    //veritable
    //*
    
  // cout << milieu << " : " << resG << " " << resD << endl;
  int a =  max(resG[milieu], resD[milieu]);
    //cout << milieu << " " << resG[milieu] << " " << resD[milieu] << endl;
    updateChang(milieu+1);
    updateRes(milieu+1);
    return a;
    /** */
    /*
 //   cout << endl;
    ordre.clear();
    for(int i = 0; i < N; i++)
    {
        ordre[-chang[i]].push_back(i);
    }
    ordre[0].push_back({});
    int derVal = -1;
    set<pair<int, int>> intersG;
    set<pair<int, int>> intersD;
    int repG = 0, repD = 0;
    for(auto a : ordre)
    {
        int val = -a.first;
        auto ajouts = a.second;
        if(derVal == -1)    derVal = val;
        int dif = derVal-val;
        repG += dif * intersG.size();
        repD += dif*intersD.size();
        derVal = val;
     //   cout << val << endl;
        for(int nouv : ajouts)
        {
            auto it = upper_bound(inters.begin(), inters.end(), pair<int, int>(nouv, nouv+1));
            // cout << "jhl" << endl;
            auto itAv = it;
         //    cout << "jhl" << endl;
          //   cout << "jhl" << endl;
            auto itAp = it;
          //   cout << "jhl" << endl;
            pair<int, int> nouvInter = {nouv, nouv+1};
          //  cout << "jhl" << endl;
            if(itAv != inters.begin())
            {
                itAv--;
            //    cout << "jhl" << endl;
                auto av = *itAv;
                if(av.second == nouv)
                {
                    nouvInter.first == av.first;
                    inters.erase(av);
                }
            }
            if(itAp != inters.end())
            {
                auto ap = *itAp;
                if(ap.first == nouv+1)
                {
                    nouvInter.second == ap.second;
                    inters.erase(ap);
                }
            }
            inters.insert(nouvInter);
        }

    }
    return max(repG, repD);
    /** */
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N;
    for(int i = 1; i <= N; i++)
    {
        cin >> hauteur[i];
    }    
    /*/
    int deb = 0, fin = N, chang = 1;
    for(int iD = 0; iD < 2; iD++)
    {
        stack<pair<int, int>> gros;
        
        for(int i = deb; i != fin; i+= chang)
        {
            int elem = hauteur[i];
            while((!gros.empty()) && (elem > gros.top().first)) gros.pop();
            if(gros.empty())
            {
                proGrand[iD][i] = i;
            }
            else
                proGrand[iD][i] = gros.top().second;
            
            gros.push({elem, i});
        }
        deb= N-1;
        fin = -1;
        chang = -1;
    }/** */
    if(N == 1)
    {
        cout << 0;
        return 0;
    }
    int meill = INFINI;
    initChang();
    initRes();
    for(int iMil = 1; iMil <= N; iMil++)
    {
        int v = trouvercoutmin(iMil);
      //  cout << "rep " << v << endl;
        meill = min(meill,v);
    }
    cout << meill;
}

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...