#include<bits/stdc++.h>
using namespace std;
 typedef pair<int,int> pii;
 typedef pair<char,char> pcc;
 typedef long long ll;
 typedef unsigned long long ull;
 typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
typedef vector<ull> vull;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef tuple<int,int,int> tiii;
#define rkmod 1125899906842597LL
#define mod1 1000000007LL
#define mod 1000000007LL
#define mod2 1000000007LL
#define mod3 1000000009LL
#define mx9 1000000000LL
#define mx10 10000000000LL
#define mx5 100000
#define mx8 100000000LL
#define mx7 10000000LL
#define mx6 1000000LL
#define mx6_5 5000000
#define last 4444444444
 #define f first
 #define s second
 #define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define reprev(i,a,b) for(ll i=(a);i>=(b);i--)
 #define repi(i,a,b) for(int i=(a);i<=(b);i++)
#define reprevi(i,a,b) for(int i=(a);i>=(b);i--)
#define mp make_pair
#define pb push_back
#define x first
#define y second
//#define PI 3.14159265
const long double PI = 2*acos(0.0);

typedef vector<bool> vb;
void print(vb &a)
{

    for(bool i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vi &a)
{

    for(int i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vc &a)
{

    for(char i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vll &a)
{

    for(ll i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<vi> &a)
{
    for(vi i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<vll> &a)
{
    for(vll i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<double> &a)
{

    for(double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<long double> &a)
{

    for(long double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
void print(deque<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
ll dist_sq(pll a,pll b)
{
    return ((a.x-b.x)*(a.x-b.x)+ (a.y-b.y)*(a.y-b.y));
}

ll po(ll a,ll b)
{
    if(b<=0)
        return 1;
    else if(b==1)
        return a;

    ll vl = po((a*a),b/2);
    if(b%2==0)
        return vl;
    else
        return (vl)*a;
}

ll pomod(ll a,ll b)
{
    a= a%mod;
    if(b<=0)
        return 1%mod;
    else if(b==1)
        return a%mod;

    ll vl = pomod((a*a)%mod,b/2);
    vl = vl%mod;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mod;
}

ll pomod(ll a,ll b,ll mo)
{
    a= a%mo;
    if(b<=0)
        return 1%mo;
    else if(b==1)
        return a%mo;

    ll vl = pomod((a*a)%mo,b/2);
    vl = vl%mo;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mo;
}
ll factmod(ll n, ll mo)
{
    ll val=n;
    ll ans =1;
    while(val>=1)
    {
        ans = (ans*val)%mo;
        val--;
    }

    return ans;
}
ll inv(ll a,ll mo)
{
    return pomod(a,mo-2,mo);
}

ll combinationMod(ll n, ll i)
{
    ll ans = 1;
    ans = (ans * factmod(n,mod))%mod;
    ll invVal =  (inv(factmod(i,mod),mod)%mod * inv(factmod(n-i,mod),mod)%mod)%mod;
    ans = (ans * invVal)%mod;
    return ans;
}

vector<vll> preComputeCombinationMod(int n)
{
    vector<vll> comb(n+1,vll(n+1,0));
    comb[0][0]=1;
    rep(i,1,n)
    {
        comb[i][0] = 1;
        comb[0][i] = 0;
    }

    rep(i,1,n)
    {
        rep(j,1,i)
        {
            comb[i][j] = (comb[i-1][j-1]%mod + comb[i-1][j]%mod)%mod;
        }
    }

    return comb;
}
ll floorlog2(ll n)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=2;
    }

    return h-1;
}
ll floorlog2(ll n,ll b)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=b;
    }

    return h-1;
}

class Trie {
    private:
    vector<Trie*> children;
    bool this_inserted = false;
public:
    /** Initialize your data structure here. */
    Trie() {
        children.resize(26,NULL);
        this_inserted = false;
    }

    /** Inserts a word into the trie. */
    void insert(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                cur->children[ind] = new Trie();

            }
            cur = cur->children[ind];
        }

        cur->this_inserted = true;
    }

    /** Returns if the word is in the trie. */
    bool search(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return cur->this_inserted;

    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        string word = prefix ;

      Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return true;
    }
};

class FenwickTree
{
    public:
    vll BIT;

    FenwickTree(int n)
    {
        BIT.resize(n+1,0);
    }
    FenwickTree(vll a)
    {
        int n = a.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,a[i]);
        }
    }
    FenwickTree(vi a)
    {
        vll b(a.begin(),a.end());

        int n = b.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,b[i]);
        }
    }

    void update(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        int x = ind;
        int sz = BIT.size();

        while(x<sz)
        {
            BIT[x]+=val;
            x += (x&-x);
        }
    }

    void set(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        ll currentVal = query(ind,ind);
        update(ind,val-currentVal);
    }
    ll query(int l, int r)
    {
        assert(0<=l and r<BIT.size());

        if(r<l)
        {
            return 0;
        }
        else
            return prefQuery(r) - prefQuery(l-1);
    }
    ll prefQuery(int ind)
    {
        assert(0<=ind and ind<BIT.size());
        int x = ind;
        ll sum = 0;
        while(x>0)
        {
            sum+=BIT[x];
            x-=(x&-x);
        }

        return sum;
    }
};
vll getPrimes(ll highestNum){

    vb isPrime(highestNum+5,true);
    vll primes;
    rep(i,2,highestNum){
        if(isPrime[i])
        {   primes.push_back(i);
            ll j = i;
            while(j*i<=highestNum){
                isPrime[j*i]=false;
                j++;
            }
        }
    }
    return primes;
}
ll getMultiplicity(ll num, ll prime){
    ll mult = 0;
    while(num%prime==0){
        mult+=1;
        num/=prime;
    }
    return mult;
}
vll getPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vll multcities(sz,0);

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return multcities;
        else
        {
            multcities[i] = getMultiplicity(num,prime);
            ll di = po(prime,multcities[i]);
            num = num/di;
        }
    }
    return multcities;
}

map<ll,ll> getMapPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    map<ll,ll> primeFac;
    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            primeFac[prime] = getMultiplicity(num,prime);
            ll di = po(prime,primeFac[prime]);
            num = num/di;
        }
    }
    return primeFac;
}
vpll getListPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vpll primeFac;

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            ll mult = getMultiplicity(num,prime);
            ll di = po(prime,mult);
            num = num/di;

            if(mult>0){
                primeFac.push_back(make_pair(prime,mult));
            }
        }
    }
    return primeFac;
}
vi compute_z(string s)
{
    int n = s.length();
    vi z(n,0);
    int l=0,r=0;
    z[0]=n;
    rep(i,1,n-1)
    {
        if(r<i)
        {
            l=r=i;
            int j = 0;
            if(s[0]!=s[i])
            {
                continue;
            }

            while(j<n and s[j] == s[i+j])
            {
                j++;
            }
            r = i+j-1;
            z[i] = r-i+1;
        }
        else
        {
            int beta = r-i+1;
            int k = i-l;

            if(z[k]<beta)
            {

                z[i]=z[k];

            }
            else
            {
                int j = 0;
                l = i;
                while(r<n and s[r]==s[r-l])
                {
                    r+=1;
                }
                r-=1;

                z[i] = r-i+1;

            }
        }
    }

    return z;
}

vi getOccurences(string s, string t){

     string comb = t + "$" + s;

     auto z_vals = compute_z(comb);

     int n = s.size();
     int t_sz = t.size();

     vi occ;

     rep(i,0,n-1)
     {
         if(z_vals[t_sz + 1 +  i]==t_sz){
             occ.push_back(i);
         }
     }
     return occ;
}

class DSU{
    private:
    vi parent;
    vi size;
    public:
    DSU(int n){
        parent.resize(n+5,0);
        size.resize(n+5,0);
        rep(i,1,n){
            parent[i]=i;
            size[i] = 1;
        }
    }
    vi getParents(){
        return parent;
    }
     vi getSizes(){
        return size;
    }
    int getRoot(int node){
       int par = parent[node];
       if(parent[par] == par){
           return par;
       }

       int root = getRoot(par);

       parent[node] = root;

       return root;
    }

    bool checkSame(int a, int b){
        return getRoot(a)==getRoot(b);
    }

    void connectNodes(int a, int b){
        int root1 = getRoot(a);
        int root2 = getRoot(b);

        if(size[root1] < size[root2]){
            swap(root1,root2);
        }

        parent[root2] = root1;
        size[root1] += size[root2];
    }
};

class SegmentTreeNode{
    private:

    ll total;
    ll pendingUpdate;

    public:
    int start,end;

    SegmentTreeNode(): total(0), start(-1),end(-1),pendingUpdate(0){}

    void assignLeaf(ll value, int start, int end){
        total = value;
        this->start = start;
        this->end = end;
    }
    void merge(SegmentTreeNode &left, SegmentTreeNode&right){
        this->start = left.start;
        this->end = right.end;
        ll leftTotal = left.getValue();
        ll rightTotal = right.getValue();

        if(left.ifPendingUpdate()){
            leftTotal += left.getSegmentSize() * left.getPendingUpdate();
        }

        if(right.ifPendingUpdate()){
            rightTotal += right.getSegmentSize() * right.getPendingUpdate();
        }
        this->total = leftTotal + rightTotal;

    }
    ll getValue(){
        return total;
    }

    ll getPendingUpdate(){
        return pendingUpdate;
    }
    bool ifPendingUpdate(){
        return pendingUpdate!=0;
    }

    void applyPendingUpdate(){
        this->total += (this->pendingUpdate) * (this->getSegmentSize());
        this->pendingUpdate = 0;
    }

    void addUpdate(ll val){
        this->pendingUpdate += val;
    }

    int getSegmentSize(){
        return (end-start + 1);
    }
};

class SegmentTree{

    public:
    int N;
    SegmentTree(vll &arr){

        this->N = arr.size();
        this-> treeSize = getSegmentTreeSize(this->N);
        //cout<<"N treeSize:" <<N<<" "<<treeSize<<"\n";
        nodes.resize(this->treeSize);

        this->buildTree(arr,1,0,N-1);
    }

     void updateRange(int startPos, int endPos, ll val){
         //flip all coins in [startPos,endPos]
         updateRange(1,startPos,endPos,val);
     }
    ll getValue(int startPos, int endPos){
        auto res = getValue(1,startPos,endPos);
        return res.getValue();
    }
    private:
     vector<SegmentTreeNode> nodes;

     int treeSize;

     void buildTree(vll &arr,int stIndex, int left, int right){
         if(left==right){
             this->nodes[stIndex].assignLeaf(arr[left],left,right);
             return;
         }

         int mid = (left+right)/2;
         int leftIndex = 2*stIndex,rightIndex = leftIndex+1;

         buildTree(arr,leftIndex,left,mid);
         buildTree(arr,rightIndex,mid+1,right);

         nodes[stIndex].merge(nodes[leftIndex],nodes[rightIndex]);
     }

    void updateRange(int stIndex, int startPos, int endPos, ll val){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            nodes[stIndex].addUpdate(val);
            return;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        if(endPos<=mid){
            updateRange(leftChildIndex,startPos,endPos,val);
        }else if(startPos>mid){
            updateRange(rightChildIndex,startPos,endPos,val);
        }else{
            updateRange(leftChildIndex,startPos,mid,val);
            updateRange(rightChildIndex,mid+1,endPos,val);
        }

        nodes[stIndex].merge(nodes[leftChildIndex],nodes[rightChildIndex]);
    }

    SegmentTreeNode getValue(int stIndex,int startPos, int endPos){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            auto result = nodes[stIndex];
            if(result.ifPendingUpdate())
                result.applyPendingUpdate();

            return result;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        SegmentTreeNode result;

        if(endPos<=mid){
            result = getValue(leftChildIndex,startPos,endPos);
        }else if(startPos>mid){
            result = getValue(rightChildIndex,startPos,endPos);
        }else{
            auto leftResult = getValue(leftChildIndex,startPos,mid);
            auto rightResult = getValue(rightChildIndex,mid+1,endPos);

            result.merge(leftResult,rightResult);
        }

        if(nodes[stIndex].ifPendingUpdate()){
            result.addUpdate(nodes[stIndex].getPendingUpdate());
            result.applyPendingUpdate();
        }

        return result;
    }
     int getSegmentTreeSize(int N){
         int x = 1;
         while(x<N){
             x = x*2;
         }
         return x*2;
     }
};

int main(void)
{
    ios_base::sync_with_stdio(false);
    int n;
    cin>>n;
    vi a(n,0);
    rep(i,0,n-1)
        cin>>a[i];
    vi t_death(n,-1);

    vi stack;

    stack.push_back(0);
    int ans = 0;
    rep(i,1,n-1){
        t_death[i]=0;
        while(!stack.empty() && a[stack.back()]<a[i]){
            t_death[i] = max(t_death[i],t_death[stack.back()]+1);
            stack.pop_back();
        }
        if(stack.empty()){
            t_death[i] = -1;
        }
        stack.push_back(i);
        ans = max(t_death[i]+1,ans);
    }
    //print(t_death);
    cout<<ans;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
 typedef pair<int,int> pii;
 typedef pair<char,char> pcc;
 typedef long long ll;
 typedef unsigned long long ull;
 typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
typedef vector<ull> vull;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef tuple<int,int,int> tiii;
#define rkmod 1125899906842597LL
#define mod1 1000000007LL
#define mod 1000000007LL
#define mod2 1000000007LL
#define mod3 1000000009LL
#define mx9 1000000000LL
#define mx10 10000000000LL
#define mx5 100000
#define mx8 100000000LL
#define mx7 10000000LL
#define mx6 1000000LL
#define mx6_5 5000000
#define last 4444444444
 #define f first
 #define s second
 #define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define reprev(i,a,b) for(ll i=(a);i>=(b);i--)
 #define repi(i,a,b) for(int i=(a);i<=(b);i++)
#define reprevi(i,a,b) for(int i=(a);i>=(b);i--)
#define mp make_pair
#define pb push_back
#define x first
#define y second
//#define PI 3.14159265
const long double PI = 2*acos(0.0);

typedef vector<bool> vb;
void print(vb &a)
{

    for(bool i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vi &a)
{

    for(int i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vc &a)
{

    for(char i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vll &a)
{

    for(ll i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<vi> &a)
{
    for(vi i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<vll> &a)
{
    for(vll i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<double> &a)
{

    for(double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<long double> &a)
{

    for(long double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
void print(deque<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
ll dist_sq(pll a,pll b)
{
    return ((a.x-b.x)*(a.x-b.x)+ (a.y-b.y)*(a.y-b.y));
}

ll po(ll a,ll b)
{
    if(b<=0)
        return 1;
    else if(b==1)
        return a;

    ll vl = po((a*a),b/2);
    if(b%2==0)
        return vl;
    else
        return (vl)*a;
}

ll pomod(ll a,ll b)
{
    a= a%mod;
    if(b<=0)
        return 1%mod;
    else if(b==1)
        return a%mod;

    ll vl = pomod((a*a)%mod,b/2);
    vl = vl%mod;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mod;
}

ll pomod(ll a,ll b,ll mo)
{
    a= a%mo;
    if(b<=0)
        return 1%mo;
    else if(b==1)
        return a%mo;

    ll vl = pomod((a*a)%mo,b/2);
    vl = vl%mo;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mo;
}
ll factmod(ll n, ll mo)
{
    ll val=n;
    ll ans =1;
    while(val>=1)
    {
        ans = (ans*val)%mo;
        val--;
    }

    return ans;
}
ll inv(ll a,ll mo)
{
    return pomod(a,mo-2,mo);
}

ll combinationMod(ll n, ll i)
{
    ll ans = 1;
    ans = (ans * factmod(n,mod))%mod;
    ll invVal =  (inv(factmod(i,mod),mod)%mod * inv(factmod(n-i,mod),mod)%mod)%mod;
    ans = (ans * invVal)%mod;
    return ans;
}

vector<vll> preComputeCombinationMod(int n)
{
    vector<vll> comb(n+1,vll(n+1,0));
    comb[0][0]=1;
    rep(i,1,n)
    {
        comb[i][0] = 1;
        comb[0][i] = 0;
    }

    rep(i,1,n)
    {
        rep(j,1,i)
        {
            comb[i][j] = (comb[i-1][j-1]%mod + comb[i-1][j]%mod)%mod;
        }
    }

    return comb;
}
ll floorlog2(ll n)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=2;
    }

    return h-1;
}
ll floorlog2(ll n,ll b)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=b;
    }

    return h-1;
}

class Trie {
    private:
    vector<Trie*> children;
    bool this_inserted = false;
public:
    /** Initialize your data structure here. */
    Trie() {
        children.resize(26,NULL);
        this_inserted = false;
    }

    /** Inserts a word into the trie. */
    void insert(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                cur->children[ind] = new Trie();

            }
            cur = cur->children[ind];
        }

        cur->this_inserted = true;
    }

    /** Returns if the word is in the trie. */
    bool search(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return cur->this_inserted;

    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        string word = prefix ;

      Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return true;
    }
};

class FenwickTree
{
    public:
    vll BIT;

    FenwickTree(int n)
    {
        BIT.resize(n+1,0);
    }
    FenwickTree(vll a)
    {
        int n = a.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,a[i]);
        }
    }
    FenwickTree(vi a)
    {
        vll b(a.begin(),a.end());

        int n = b.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,b[i]);
        }
    }

    void update(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        int x = ind;
        int sz = BIT.size();

        while(x<sz)
        {
            BIT[x]+=val;
            x += (x&-x);
        }
    }

    void set(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        ll currentVal = query(ind,ind);
        update(ind,val-currentVal);
    }
    ll query(int l, int r)
    {
        assert(0<=l and r<BIT.size());

        if(r<l)
        {
            return 0;
        }
        else
            return prefQuery(r) - prefQuery(l-1);
    }
    ll prefQuery(int ind)
    {
        assert(0<=ind and ind<BIT.size());
        int x = ind;
        ll sum = 0;
        while(x>0)
        {
            sum+=BIT[x];
            x-=(x&-x);
        }

        return sum;
    }
};
vll getPrimes(ll highestNum){

    vb isPrime(highestNum+5,true);
    vll primes;
    rep(i,2,highestNum){
        if(isPrime[i])
        {   primes.push_back(i);
            ll j = i;
            while(j*i<=highestNum){
                isPrime[j*i]=false;
                j++;
            }
        }
    }
    return primes;
}
ll getMultiplicity(ll num, ll prime){
    ll mult = 0;
    while(num%prime==0){
        mult+=1;
        num/=prime;
    }
    return mult;
}
vll getPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vll multcities(sz,0);

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return multcities;
        else
        {
            multcities[i] = getMultiplicity(num,prime);
            ll di = po(prime,multcities[i]);
            num = num/di;
        }
    }
    return multcities;
}

map<ll,ll> getMapPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    map<ll,ll> primeFac;
    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            primeFac[prime] = getMultiplicity(num,prime);
            ll di = po(prime,primeFac[prime]);
            num = num/di;
        }
    }
    return primeFac;
}
vpll getListPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vpll primeFac;

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            ll mult = getMultiplicity(num,prime);
            ll di = po(prime,mult);
            num = num/di;

            if(mult>0){
                primeFac.push_back(make_pair(prime,mult));
            }
        }
    }
    return primeFac;
}
vi compute_z(string s)
{
    int n = s.length();
    vi z(n,0);
    int l=0,r=0;
    z[0]=n;
    rep(i,1,n-1)
    {
        if(r<i)
        {
            l=r=i;
            int j = 0;
            if(s[0]!=s[i])
            {
                continue;
            }

            while(j<n and s[j] == s[i+j])
            {
                j++;
            }
            r = i+j-1;
            z[i] = r-i+1;
        }
        else
        {
            int beta = r-i+1;
            int k = i-l;

            if(z[k]<beta)
            {

                z[i]=z[k];

            }
            else
            {
                int j = 0;
                l = i;
                while(r<n and s[r]==s[r-l])
                {
                    r+=1;
                }
                r-=1;

                z[i] = r-i+1;

            }
        }
    }

    return z;
}

vi getOccurences(string s, string t){

     string comb = t + "$" + s;

     auto z_vals = compute_z(comb);

     int n = s.size();
     int t_sz = t.size();

     vi occ;

     rep(i,0,n-1)
     {
         if(z_vals[t_sz + 1 +  i]==t_sz){
             occ.push_back(i);
         }
     }
     return occ;
}

class DSU{
    private:
    vi parent;
    vi size;
    public:
    DSU(int n){
        parent.resize(n+5,0);
        size.resize(n+5,0);
        rep(i,1,n){
            parent[i]=i;
            size[i] = 1;
        }
    }
    vi getParents(){
        return parent;
    }
     vi getSizes(){
        return size;
    }
    int getRoot(int node){
       int par = parent[node];
       if(parent[par] == par){
           return par;
       }

       int root = getRoot(par);

       parent[node] = root;

       return root;
    }

    bool checkSame(int a, int b){
        return getRoot(a)==getRoot(b);
    }

    void connectNodes(int a, int b){
        int root1 = getRoot(a);
        int root2 = getRoot(b);

        if(size[root1] < size[root2]){
            swap(root1,root2);
        }

        parent[root2] = root1;
        size[root1] += size[root2];
    }
};

class SegmentTreeNode{
    private:

    ll total;
    ll pendingUpdate;

    public:
    int start,end;

    SegmentTreeNode(): total(0), start(-1),end(-1),pendingUpdate(0){}

    void assignLeaf(ll value, int start, int end){
        total = value;
        this->start = start;
        this->end = end;
    }
    void merge(SegmentTreeNode &left, SegmentTreeNode&right){
        this->start = left.start;
        this->end = right.end;
        ll leftTotal = left.getValue();
        ll rightTotal = right.getValue();

        if(left.ifPendingUpdate()){
            leftTotal += left.getSegmentSize() * left.getPendingUpdate();
        }

        if(right.ifPendingUpdate()){
            rightTotal += right.getSegmentSize() * right.getPendingUpdate();
        }
        this->total = leftTotal + rightTotal;

    }
    ll getValue(){
        return total;
    }

    ll getPendingUpdate(){
        return pendingUpdate;
    }
    bool ifPendingUpdate(){
        return pendingUpdate!=0;
    }

    void applyPendingUpdate(){
        this->total += (this->pendingUpdate) * (this->getSegmentSize());
        this->pendingUpdate = 0;
    }

    void addUpdate(ll val){
        this->pendingUpdate += val;
    }

    int getSegmentSize(){
        return (end-start + 1);
    }
};

class SegmentTree{

    public:
    int N;
    SegmentTree(vll &arr){

        this->N = arr.size();
        this-> treeSize = getSegmentTreeSize(this->N);
        //cout<<"N treeSize:" <<N<<" "<<treeSize<<"\n";
        nodes.resize(this->treeSize);

        this->buildTree(arr,1,0,N-1);
    }

     void updateRange(int startPos, int endPos, ll val){
         //flip all coins in [startPos,endPos]
         updateRange(1,startPos,endPos,val);
     }
    ll getValue(int startPos, int endPos){
        auto res = getValue(1,startPos,endPos);
        return res.getValue();
    }
    private:
     vector<SegmentTreeNode> nodes;

     int treeSize;

     void buildTree(vll &arr,int stIndex, int left, int right){
         if(left==right){
             this->nodes[stIndex].assignLeaf(arr[left],left,right);
             return;
         }

         int mid = (left+right)/2;
         int leftIndex = 2*stIndex,rightIndex = leftIndex+1;

         buildTree(arr,leftIndex,left,mid);
         buildTree(arr,rightIndex,mid+1,right);

         nodes[stIndex].merge(nodes[leftIndex],nodes[rightIndex]);
     }

    void updateRange(int stIndex, int startPos, int endPos, ll val){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            nodes[stIndex].addUpdate(val);
            return;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        if(endPos<=mid){
            updateRange(leftChildIndex,startPos,endPos,val);
        }else if(startPos>mid){
            updateRange(rightChildIndex,startPos,endPos,val);
        }else{
            updateRange(leftChildIndex,startPos,mid,val);
            updateRange(rightChildIndex,mid+1,endPos,val);
        }

        nodes[stIndex].merge(nodes[leftChildIndex],nodes[rightChildIndex]);
    }

    SegmentTreeNode getValue(int stIndex,int startPos, int endPos){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            auto result = nodes[stIndex];
            if(result.ifPendingUpdate())
                result.applyPendingUpdate();

            return result;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        SegmentTreeNode result;

        if(endPos<=mid){
            result = getValue(leftChildIndex,startPos,endPos);
        }else if(startPos>mid){
            result = getValue(rightChildIndex,startPos,endPos);
        }else{
            auto leftResult = getValue(leftChildIndex,startPos,mid);
            auto rightResult = getValue(rightChildIndex,mid+1,endPos);

            result.merge(leftResult,rightResult);
        }

        if(nodes[stIndex].ifPendingUpdate()){
            result.addUpdate(nodes[stIndex].getPendingUpdate());
            result.applyPendingUpdate();
        }

        return result;
    }
     int getSegmentTreeSize(int N){
         int x = 1;
         while(x<N){
             x = x*2;
         }
         return x*2;
     }
};

int main(void)
{
    ios_base::sync_with_stdio(false);
    int n;
    cin>>n;
    vi a(n+5,0);
    vi prev(n,-1);
    vi nex(n,n);
    vector<bool> is_del(n,false);

    rep(i,0,n-1){
        cin>>a[i];
    }
    rep(i,1,n-1){
        prev[i] = i-1;
    }

    reprev(i,n-2,0){
        nex[i] = i+1;
    }

    int ans = 0;

    while(true){
        bool is_changed = false;

        int prev_val = a[0];
        int prev_ind = 0;

        int cur_val = a[nex[0]];
        int cur_ind = nex[0];

        while(cur_ind<n){
            if(is_del[cur_ind] or cur_val<a[prev[cur_ind]]){
                is_changed = true;
                is_del[cur_ind] = true;

                cur_ind = nex[cur_ind];

                if(cur_ind>=n){
                    nex[prev_ind] = n;
                    continue;
                }
                cur_val = a[cur_ind];
            } else{
                nex[prev_ind] = cur_ind;
                prev[cur_ind] = prev_ind;

                prev_ind = cur_ind;
                prev_val =cur_val;

                cur_ind = nex[cur_ind];

                if(cur_ind>=n){
                    continue;
                }
                cur_val = a[cur_ind];

            }
        }
        if(!is_changed){
            cout<<ans<<"\n";
            return 0;
        }
        ans+=1;
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
 typedef pair<int,int> pii;
 typedef pair<char,char> pcc;
 typedef long long ll;
 typedef unsigned long long ull;
 typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
typedef vector<ull> vull;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef tuple<int,int,int> tiii;
#define rkmod 1125899906842597LL
#define mod1 1000000007LL
#define mod 1000000007LL
#define mod2 1000000007LL
#define mod3 1000000009LL
#define mx9 1000000000LL
#define mx10 10000000000LL
#define mx5 100000
#define mx8 100000000LL
#define mx7 10000000LL
#define mx6 1000000LL
#define mx6_5 5000000
#define last 4444444444
 #define f first
 #define s second
 #define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define reprev(i,a,b) for(ll i=(a);i>=(b);i--)
 #define repi(i,a,b) for(int i=(a);i<=(b);i++)
#define reprevi(i,a,b) for(int i=(a);i>=(b);i--)
#define mp make_pair
#define pb push_back
#define x first
#define y second
//#define PI 3.14159265
const long double PI = 2*acos(0.0);

typedef vector<bool> vb;
void print(vb &a)
{

    for(bool i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vi &a)
{

    for(int i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vc &a)
{

    for(char i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vll &a)
{

    for(ll i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<vi> &a)
{
    for(vi i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<vll> &a)
{
    for(vll i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<double> &a)
{

    for(double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<long double> &a)
{

    for(long double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
void print(deque<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
ll dist_sq(pll a,pll b)
{
    return ((a.x-b.x)*(a.x-b.x)+ (a.y-b.y)*(a.y-b.y));
}

ll po(ll a,ll b)
{
    if(b<=0)
        return 1;
    else if(b==1)
        return a;

    ll vl = po((a*a),b/2);
    if(b%2==0)
        return vl;
    else
        return (vl)*a;
}

ll pomod(ll a,ll b)
{
    a= a%mod;
    if(b<=0)
        return 1%mod;
    else if(b==1)
        return a%mod;

    ll vl = pomod((a*a)%mod,b/2);
    vl = vl%mod;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mod;
}

ll pomod(ll a,ll b,ll mo)
{
    a= a%mo;
    if(b<=0)
        return 1%mo;
    else if(b==1)
        return a%mo;

    ll vl = pomod((a*a)%mo,b/2);
    vl = vl%mo;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mo;
}
ll factmod(ll n, ll mo)
{
    ll val=n;
    ll ans =1;
    while(val>=1)
    {
        ans = (ans*val)%mo;
        val--;
    }

    return ans;
}
ll inv(ll a,ll mo)
{
    return pomod(a,mo-2,mo);
}

ll combinationMod(ll n, ll i)
{
    ll ans = 1;
    ans = (ans * factmod(n,mod))%mod;
    ll invVal =  (inv(factmod(i,mod),mod)%mod * inv(factmod(n-i,mod),mod)%mod)%mod;
    ans = (ans * invVal)%mod;
    return ans;
}

vector<vll> preComputeCombinationMod(int n)
{
    vector<vll> comb(n+1,vll(n+1,0));
    comb[0][0]=1;
    rep(i,1,n)
    {
        comb[i][0] = 1;
        comb[0][i] = 0;
    }

    rep(i,1,n)
    {
        rep(j,1,i)
        {
            comb[i][j] = (comb[i-1][j-1]%mod + comb[i-1][j]%mod)%mod;
        }
    }

    return comb;
}
ll floorlog2(ll n)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=2;
    }

    return h-1;
}
ll floorlog2(ll n,ll b)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=b;
    }

    return h-1;
}

class Trie {
    private:
    vector<Trie*> children;
    bool this_inserted = false;
public:
    /** Initialize your data structure here. */
    Trie() {
        children.resize(26,NULL);
        this_inserted = false;
    }

    /** Inserts a word into the trie. */
    void insert(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                cur->children[ind] = new Trie();

            }
            cur = cur->children[ind];
        }

        cur->this_inserted = true;
    }

    /** Returns if the word is in the trie. */
    bool search(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return cur->this_inserted;

    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        string word = prefix ;

      Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return true;
    }
};

class FenwickTree
{
    public:
    vll BIT;

    FenwickTree(int n)
    {
        BIT.resize(n+1,0);
    }
    FenwickTree(vll a)
    {
        int n = a.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,a[i]);
        }
    }
    FenwickTree(vi a)
    {
        vll b(a.begin(),a.end());

        int n = b.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,b[i]);
        }
    }

    void update(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        int x = ind;
        int sz = BIT.size();

        while(x<sz)
        {
            BIT[x]+=val;
            x += (x&-x);
        }
    }

    void set(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        ll currentVal = query(ind,ind);
        update(ind,val-currentVal);
    }
    ll query(int l, int r)
    {
        assert(0<=l and r<BIT.size());

        if(r<l)
        {
            return 0;
        }
        else
            return prefQuery(r) - prefQuery(l-1);
    }
    ll prefQuery(int ind)
    {
        assert(0<=ind and ind<BIT.size());
        int x = ind;
        ll sum = 0;
        while(x>0)
        {
            sum+=BIT[x];
            x-=(x&-x);
        }

        return sum;
    }
};
vll getPrimes(ll highestNum){

    vb isPrime(highestNum+5,true);
    vll primes;
    rep(i,2,highestNum){
        if(isPrime[i])
        {   primes.push_back(i);
            ll j = i;
            while(j*i<=highestNum){
                isPrime[j*i]=false;
                j++;
            }
        }
    }
    return primes;
}
ll getMultiplicity(ll num, ll prime){
    ll mult = 0;
    while(num%prime==0){
        mult+=1;
        num/=prime;
    }
    return mult;
}
vll getPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vll multcities(sz,0);

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return multcities;
        else
        {
            multcities[i] = getMultiplicity(num,prime);
            ll di = po(prime,multcities[i]);
            num = num/di;
        }
    }
    return multcities;
}

map<ll,ll> getMapPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    map<ll,ll> primeFac;
    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            primeFac[prime] = getMultiplicity(num,prime);
            ll di = po(prime,primeFac[prime]);
            num = num/di;
        }
    }
    return primeFac;
}
vpll getListPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vpll primeFac;

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            ll mult = getMultiplicity(num,prime);
            ll di = po(prime,mult);
            num = num/di;

            if(mult>0){
                primeFac.push_back(make_pair(prime,mult));
            }
        }
    }
    return primeFac;
}
vi compute_z(string s)
{
    int n = s.length();
    vi z(n,0);
    int l=0,r=0;
    z[0]=n;
    rep(i,1,n-1)
    {
        if(r<i)
        {
            l=r=i;
            int j = 0;
            if(s[0]!=s[i])
            {
                continue;
            }

            while(j<n and s[j] == s[i+j])
            {
                j++;
            }
            r = i+j-1;
            z[i] = r-i+1;
        }
        else
        {
            int beta = r-i+1;
            int k = i-l;

            if(z[k]<beta)
            {

                z[i]=z[k];

            }
            else
            {
                int j = 0;
                l = i;
                while(r<n and s[r]==s[r-l])
                {
                    r+=1;
                }
                r-=1;

                z[i] = r-i+1;

            }
        }
    }

    return z;
}

vi getOccurences(string s, string t){

     string comb = t + "$" + s;

     auto z_vals = compute_z(comb);

     int n = s.size();
     int t_sz = t.size();

     vi occ;

     rep(i,0,n-1)
     {
         if(z_vals[t_sz + 1 +  i]==t_sz){
             occ.push_back(i);
         }
     }
     return occ;
}

class DSU{
    private:
    vi parent;
    vi size;
    public:
    DSU(int n){
        parent.resize(n+5,0);
        size.resize(n+5,0);
        rep(i,1,n){
            parent[i]=i;
            size[i] = 1;
        }
    }
    vi getParents(){
        return parent;
    }
     vi getSizes(){
        return size;
    }
    int getRoot(int node){
       int par = parent[node];
       if(parent[par] == par){
           return par;
       }

       int root = getRoot(par);

       parent[node] = root;

       return root;
    }

    bool checkSame(int a, int b){
        return getRoot(a)==getRoot(b);
    }

    void connectNodes(int a, int b){
        int root1 = getRoot(a);
        int root2 = getRoot(b);

        if(size[root1] < size[root2]){
            swap(root1,root2);
        }

        parent[root2] = root1;
        size[root1] += size[root2];
    }
};

class SegmentTreeNode{
    private:

    ll total;
    ll pendingUpdate;

    public:
    int start,end;

    SegmentTreeNode(): total(0), start(-1),end(-1),pendingUpdate(0){}

    void assignLeaf(ll value, int start, int end){
        total = value;
        this->start = start;
        this->end = end;
    }
    void merge(SegmentTreeNode &left, SegmentTreeNode&right){
        this->start = left.start;
        this->end = right.end;
        ll leftTotal = left.getValue();
        ll rightTotal = right.getValue();

        if(left.ifPendingUpdate()){
            leftTotal += left.getSegmentSize() * left.getPendingUpdate();
        }

        if(right.ifPendingUpdate()){
            rightTotal += right.getSegmentSize() * right.getPendingUpdate();
        }
        this->total = leftTotal + rightTotal;

    }
    ll getValue(){
        return total;
    }

    ll getPendingUpdate(){
        return pendingUpdate;
    }
    bool ifPendingUpdate(){
        return pendingUpdate!=0;
    }

    void applyPendingUpdate(){
        this->total += (this->pendingUpdate) * (this->getSegmentSize());
        this->pendingUpdate = 0;
    }

    void addUpdate(ll val){
        this->pendingUpdate += val;
    }

    int getSegmentSize(){
        return (end-start + 1);
    }
};

class SegmentTree{

    public:
    int N;
    SegmentTree(vll &arr){

        this->N = arr.size();
        this-> treeSize = getSegmentTreeSize(this->N);
        //cout<<"N treeSize:" <<N<<" "<<treeSize<<"\n";
        nodes.resize(this->treeSize);

        this->buildTree(arr,1,0,N-1);
    }

     void updateRange(int startPos, int endPos, ll val){
         //flip all coins in [startPos,endPos]
         updateRange(1,startPos,endPos,val);
     }
    ll getValue(int startPos, int endPos){
        auto res = getValue(1,startPos,endPos);
        return res.getValue();
    }
    private:
     vector<SegmentTreeNode> nodes;

     int treeSize;

     void buildTree(vll &arr,int stIndex, int left, int right){
         if(left==right){
             this->nodes[stIndex].assignLeaf(arr[left],left,right);
             return;
         }

         int mid = (left+right)/2;
         int leftIndex = 2*stIndex,rightIndex = leftIndex+1;

         buildTree(arr,leftIndex,left,mid);
         buildTree(arr,rightIndex,mid+1,right);

         nodes[stIndex].merge(nodes[leftIndex],nodes[rightIndex]);
     }

    void updateRange(int stIndex, int startPos, int endPos, ll val){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            nodes[stIndex].addUpdate(val);
            return;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        if(endPos<=mid){
            updateRange(leftChildIndex,startPos,endPos,val);
        }else if(startPos>mid){
            updateRange(rightChildIndex,startPos,endPos,val);
        }else{
            updateRange(leftChildIndex,startPos,mid,val);
            updateRange(rightChildIndex,mid+1,endPos,val);
        }

        nodes[stIndex].merge(nodes[leftChildIndex],nodes[rightChildIndex]);
    }

    SegmentTreeNode getValue(int stIndex,int startPos, int endPos){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            auto result = nodes[stIndex];
            if(result.ifPendingUpdate())
                result.applyPendingUpdate();

            return result;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        SegmentTreeNode result;

        if(endPos<=mid){
            result = getValue(leftChildIndex,startPos,endPos);
        }else if(startPos>mid){
            result = getValue(rightChildIndex,startPos,endPos);
        }else{
            auto leftResult = getValue(leftChildIndex,startPos,mid);
            auto rightResult = getValue(rightChildIndex,mid+1,endPos);

            result.merge(leftResult,rightResult);
        }

        if(nodes[stIndex].ifPendingUpdate()){
            result.addUpdate(nodes[stIndex].getPendingUpdate());
            result.applyPendingUpdate();
        }

        return result;
    }
     int getSegmentTreeSize(int N){
         int x = 1;
         while(x<N){
             x = x*2;
         }
         return x*2;
     }
};

int main(void)
{
    ios_base::sync_with_stdio(false);
    int n;
    cin>>n;
    vi a(n,0);
    rep(i,0,n-1)
        cin>>a[i];
    vi t_death(n,-1);

    vi stack;

    stack.push_back(0);
    int ans = 0;
    rep(i,1,n-1){
        t_death[i]=0;
        while(!stack.empty() && a[stack.back()]<a[i]){
            t_death[i] = max(t_death[i],t_death[stack.back()]+1);
            stack.pop_back();
        }
        if(stack.empty()){
            t_death[i] = -1;
        }
        ans = max(t_death[i]+1,ans);
    }

    cout<<ans;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
 typedef pair<int,int> pii;
 typedef pair<char,char> pcc;
 typedef long long ll;
 typedef unsigned long long ull;
 typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
typedef vector<ull> vull;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef tuple<int,int,int> tiii;
#define rkmod 1125899906842597LL
#define mod1 1000000007LL
#define mod 1000000007LL
#define mod2 1000000007LL
#define mod3 1000000009LL
#define mx9 1000000000LL
#define mx10 10000000000LL
#define mx5 100000
#define mx8 100000000LL
#define mx7 10000000LL
#define mx6 1000000LL
#define mx6_5 5000000
#define last 4444444444
 #define f first
 #define s second
 #define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define reprev(i,a,b) for(ll i=(a);i>=(b);i--)
 #define repi(i,a,b) for(int i=(a);i<=(b);i++)
#define reprevi(i,a,b) for(int i=(a);i>=(b);i--)
#define mp make_pair
#define pb push_back
#define x first
#define y second
//#define PI 3.14159265
const long double PI = 2*acos(0.0);

typedef vector<bool> vb;
void print(vb &a)
{

    for(bool i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vi &a)
{

    for(int i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vc &a)
{

    for(char i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vll &a)
{

    for(ll i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<vi> &a)
{
    for(vi i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<vll> &a)
{
    for(vll i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<double> &a)
{

    for(double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<long double> &a)
{

    for(long double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
void print(deque<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
ll dist_sq(pll a,pll b)
{
    return ((a.x-b.x)*(a.x-b.x)+ (a.y-b.y)*(a.y-b.y));
}

ll po(ll a,ll b)
{
    if(b<=0)
        return 1;
    else if(b==1)
        return a;

    ll vl = po((a*a),b/2);
    if(b%2==0)
        return vl;
    else
        return (vl)*a;
}

ll pomod(ll a,ll b)
{
    a= a%mod;
    if(b<=0)
        return 1%mod;
    else if(b==1)
        return a%mod;

    ll vl = pomod((a*a)%mod,b/2);
    vl = vl%mod;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mod;
}

ll pomod(ll a,ll b,ll mo)
{
    a= a%mo;
    if(b<=0)
        return 1%mo;
    else if(b==1)
        return a%mo;

    ll vl = pomod((a*a)%mo,b/2);
    vl = vl%mo;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mo;
}
ll factmod(ll n, ll mo)
{
    ll val=n;
    ll ans =1;
    while(val>=1)
    {
        ans = (ans*val)%mo;
        val--;
    }

    return ans;
}
ll inv(ll a,ll mo)
{
    return pomod(a,mo-2,mo);
}

ll combinationMod(ll n, ll i)
{
    ll ans = 1;
    ans = (ans * factmod(n,mod))%mod;
    ll invVal =  (inv(factmod(i,mod),mod)%mod * inv(factmod(n-i,mod),mod)%mod)%mod;
    ans = (ans * invVal)%mod;
    return ans;
}

vector<vll> preComputeCombinationMod(int n)
{
    vector<vll> comb(n+1,vll(n+1,0));
    comb[0][0]=1;
    rep(i,1,n)
    {
        comb[i][0] = 1;
        comb[0][i] = 0;
    }

    rep(i,1,n)
    {
        rep(j,1,i)
        {
            comb[i][j] = (comb[i-1][j-1]%mod + comb[i-1][j]%mod)%mod;
        }
    }

    return comb;
}
ll floorlog2(ll n)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=2;
    }

    return h-1;
}
ll floorlog2(ll n,ll b)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=b;
    }

    return h-1;
}

class Trie {
    private:
    vector<Trie*> children;
    bool this_inserted = false;
public:
    /** Initialize your data structure here. */
    Trie() {
        children.resize(26,NULL);
        this_inserted = false;
    }

    /** Inserts a word into the trie. */
    void insert(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                cur->children[ind] = new Trie();

            }
            cur = cur->children[ind];
        }

        cur->this_inserted = true;
    }

    /** Returns if the word is in the trie. */
    bool search(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return cur->this_inserted;

    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        string word = prefix ;

      Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return true;
    }
};

class FenwickTree
{
    public:
    vll BIT;

    FenwickTree(int n)
    {
        BIT.resize(n+1,0);
    }
    FenwickTree(vll a)
    {
        int n = a.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,a[i]);
        }
    }
    FenwickTree(vi a)
    {
        vll b(a.begin(),a.end());

        int n = b.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,b[i]);
        }
    }

    void update(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        int x = ind;
        int sz = BIT.size();

        while(x<sz)
        {
            BIT[x]+=val;
            x += (x&-x);
        }
    }

    void set(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        ll currentVal = query(ind,ind);
        update(ind,val-currentVal);
    }
    ll query(int l, int r)
    {
        assert(0<=l and r<BIT.size());

        if(r<l)
        {
            return 0;
        }
        else
            return prefQuery(r) - prefQuery(l-1);
    }
    ll prefQuery(int ind)
    {
        assert(0<=ind and ind<BIT.size());
        int x = ind;
        ll sum = 0;
        while(x>0)
        {
            sum+=BIT[x];
            x-=(x&-x);
        }

        return sum;
    }
};
vll getPrimes(ll highestNum){

    vb isPrime(highestNum+5,true);
    vll primes;
    rep(i,2,highestNum){
        if(isPrime[i])
        {   primes.push_back(i);
            ll j = i;
            while(j*i<=highestNum){
                isPrime[j*i]=false;
                j++;
            }
        }
    }
    return primes;
}
ll getMultiplicity(ll num, ll prime){
    ll mult = 0;
    while(num%prime==0){
        mult+=1;
        num/=prime;
    }
    return mult;
}
vll getPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vll multcities(sz,0);

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return multcities;
        else
        {
            multcities[i] = getMultiplicity(num,prime);
            ll di = po(prime,multcities[i]);
            num = num/di;
        }
    }
    return multcities;
}

map<ll,ll> getMapPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    map<ll,ll> primeFac;
    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            primeFac[prime] = getMultiplicity(num,prime);
            ll di = po(prime,primeFac[prime]);
            num = num/di;
        }
    }
    return primeFac;
}
vpll getListPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vpll primeFac;

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            ll mult = getMultiplicity(num,prime);
            ll di = po(prime,mult);
            num = num/di;

            if(mult>0){
                primeFac.push_back(make_pair(prime,mult));
            }
        }
    }
    return primeFac;
}
vi compute_z(string s)
{
    int n = s.length();
    vi z(n,0);
    int l=0,r=0;
    z[0]=n;
    rep(i,1,n-1)
    {
        if(r<i)
        {
            l=r=i;
            int j = 0;
            if(s[0]!=s[i])
            {
                continue;
            }

            while(j<n and s[j] == s[i+j])
            {
                j++;
            }
            r = i+j-1;
            z[i] = r-i+1;
        }
        else
        {
            int beta = r-i+1;
            int k = i-l;

            if(z[k]<beta)
            {

                z[i]=z[k];

            }
            else
            {
                int j = 0;
                l = i;
                while(r<n and s[r]==s[r-l])
                {
                    r+=1;
                }
                r-=1;

                z[i] = r-i+1;

            }
        }
    }

    return z;
}

vi getOccurences(string s, string t){

     string comb = t + "$" + s;

     auto z_vals = compute_z(comb);

     int n = s.size();
     int t_sz = t.size();

     vi occ;

     rep(i,0,n-1)
     {
         if(z_vals[t_sz + 1 +  i]==t_sz){
             occ.push_back(i);
         }
     }
     return occ;
}

class DSU{
    private:
    vi parent;
    vi size;
    public:
    DSU(int n){
        parent.resize(n+5,0);
        size.resize(n+5,0);
        rep(i,1,n){
            parent[i]=i;
            size[i] = 1;
        }
    }
    vi getParents(){
        return parent;
    }
     vi getSizes(){
        return size;
    }
    int getRoot(int node){
       int par = parent[node];
       if(parent[par] == par){
           return par;
       }

       int root = getRoot(par);

       parent[node] = root;

       return root;
    }

    bool checkSame(int a, int b){
        return getRoot(a)==getRoot(b);
    }

    void connectNodes(int a, int b){
        int root1 = getRoot(a);
        int root2 = getRoot(b);

        if(size[root1] < size[root2]){
            swap(root1,root2);
        }

        parent[root2] = root1;
        size[root1] += size[root2];
    }
};

class SegmentTreeNode{
    private:

    ll total;
    ll pendingUpdate;

    public:
    int start,end;

    SegmentTreeNode(): total(0), start(-1),end(-1),pendingUpdate(0){}

    void assignLeaf(ll value, int start, int end){
        total = value;
        this->start = start;
        this->end = end;
    }
    void merge(SegmentTreeNode &left, SegmentTreeNode&right){
        this->start = left.start;
        this->end = right.end;
        ll leftTotal = left.getValue();
        ll rightTotal = right.getValue();

        if(left.ifPendingUpdate()){
            leftTotal += left.getSegmentSize() * left.getPendingUpdate();
        }

        if(right.ifPendingUpdate()){
            rightTotal += right.getSegmentSize() * right.getPendingUpdate();
        }
        this->total = leftTotal + rightTotal;

    }
    ll getValue(){
        return total;
    }

    ll getPendingUpdate(){
        return pendingUpdate;
    }
    bool ifPendingUpdate(){
        return pendingUpdate!=0;
    }

    void applyPendingUpdate(){
        this->total += (this->pendingUpdate) * (this->getSegmentSize());
        this->pendingUpdate = 0;
    }

    void addUpdate(ll val){
        this->pendingUpdate += val;
    }

    int getSegmentSize(){
        return (end-start + 1);
    }
};

class SegmentTree{

    public:
    int N;
    SegmentTree(vll &arr){

        this->N = arr.size();
        this-> treeSize = getSegmentTreeSize(this->N);
        //cout<<"N treeSize:" <<N<<" "<<treeSize<<"\n";
        nodes.resize(this->treeSize);

        this->buildTree(arr,1,0,N-1);
    }

     void updateRange(int startPos, int endPos, ll val){
         //flip all coins in [startPos,endPos]
         updateRange(1,startPos,endPos,val);
     }
    ll getValue(int startPos, int endPos){
        auto res = getValue(1,startPos,endPos);
        return res.getValue();
    }
    private:
     vector<SegmentTreeNode> nodes;

     int treeSize;

     void buildTree(vll &arr,int stIndex, int left, int right){
         if(left==right){
             this->nodes[stIndex].assignLeaf(arr[left],left,right);
             return;
         }

         int mid = (left+right)/2;
         int leftIndex = 2*stIndex,rightIndex = leftIndex+1;

         buildTree(arr,leftIndex,left,mid);
         buildTree(arr,rightIndex,mid+1,right);

         nodes[stIndex].merge(nodes[leftIndex],nodes[rightIndex]);
     }

    void updateRange(int stIndex, int startPos, int endPos, ll val){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            nodes[stIndex].addUpdate(val);
            return;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        if(endPos<=mid){
            updateRange(leftChildIndex,startPos,endPos,val);
        }else if(startPos>mid){
            updateRange(rightChildIndex,startPos,endPos,val);
        }else{
            updateRange(leftChildIndex,startPos,mid,val);
            updateRange(rightChildIndex,mid+1,endPos,val);
        }

        nodes[stIndex].merge(nodes[leftChildIndex],nodes[rightChildIndex]);
    }

    SegmentTreeNode getValue(int stIndex,int startPos, int endPos){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            auto result = nodes[stIndex];
            if(result.ifPendingUpdate())
                result.applyPendingUpdate();

            return result;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        SegmentTreeNode result;

        if(endPos<=mid){
            result = getValue(leftChildIndex,startPos,endPos);
        }else if(startPos>mid){
            result = getValue(rightChildIndex,startPos,endPos);
        }else{
            auto leftResult = getValue(leftChildIndex,startPos,mid);
            auto rightResult = getValue(rightChildIndex,mid+1,endPos);

            result.merge(leftResult,rightResult);
        }

        if(nodes[stIndex].ifPendingUpdate()){
            result.addUpdate(nodes[stIndex].getPendingUpdate());
            result.applyPendingUpdate();
        }

        return result;
    }
     int getSegmentTreeSize(int N){
         int x = 1;
         while(x<N){
             x = x*2;
         }
         return x*2;
     }
};

int main(void)
{
    ios_base::sync_with_stdio(false);
    int n;
    cin>>n;
    vi a(n+5,0);
    vi prev(n,-1);
    vi nex(n,n);
    vector<bool> is_del(n,false);

    vi del_time(n+5,n+5);
    vi del_by(n+5,0);

    rep(i,1,n){
        cin>>a[i];
    }
    int ans = 0;
    rep(i,1,n){

        // reprev(j,i-1,1){
        //     if(a[j]>a[i] and del_time[j]>bel_max){
        //         del_t = bel_max + 1;
        //         isDel = true;
        //         break;
        //     } else if(a[j]<a[i]){
        //         bel_max = max(bel_max,del_time[j]);
        //     }
        // }
        if(a[i-1] > a[i]){
            del_by[i] = i-1;
            del_time[i] = 1;
            ans = max(ans,del_time[i]);
        }
        else{
           int j = i-1;
           int prev = del_by[j];
           bool isDel = false;
           int del_t = 0;
           int delby =0;
           while(true){
               if(j==0 or prev ==0){
                   break;
               }

               if(a[prev]>a[i]){
                   isDel =true;
                   del_t = del_time[j]+1;
                   delby = prev;
                   break;
               }
               j = prev;
               prev = del_by[prev];
           }

           if(isDel){
               del_time[i] = del_t;
               del_by[i] = prev;
               ans = max(ans,del_time[i]);
           }
        }
    }
    cout<<ans;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
 typedef pair<int,int> pii;
 typedef pair<char,char> pcc;
 typedef long long ll;
 typedef unsigned long long ull;
 typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
typedef vector<ull> vull;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef tuple<int,int,int> tiii;
#define rkmod 1125899906842597LL
#define mod1 1000000007LL
#define mod 1000000007LL
#define mod2 1000000007LL
#define mod3 1000000009LL
#define mx9 1000000000LL
#define mx10 10000000000LL
#define mx5 100000
#define mx8 100000000LL
#define mx7 10000000LL
#define mx6 1000000LL
#define mx6_5 5000000
#define last 4444444444
 #define f first
 #define s second
 #define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define reprev(i,a,b) for(ll i=(a);i>=(b);i--)
 #define repi(i,a,b) for(int i=(a);i<=(b);i++)
#define reprevi(i,a,b) for(int i=(a);i>=(b);i--)
#define mp make_pair
#define pb push_back
#define x first
#define y second
//#define PI 3.14159265
const long double PI = 2*acos(0.0);

typedef vector<bool> vb;
void print(vb &a)
{

    for(bool i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vi &a)
{

    for(int i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vc &a)
{

    for(char i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vll &a)
{

    for(ll i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<vi> &a)
{
    for(vi i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<vll> &a)
{
    for(vll i:a)
    {
        print(i);
    }
    cout<<"\n";
}
void print(vector<double> &a)
{

    for(double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<long double> &a)
{

    for(long double i:a)
    {
        cout<<i<<" ";
    }
    cout<<"\n";
}
void print(vector<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
void print(deque<pll> &a)
{

    for(pll i:a)
    {
        cout<<i.f<<" "<<i.s<<"\n";
    }
    cout<<"\n";
}
ll dist_sq(pll a,pll b)
{
    return ((a.x-b.x)*(a.x-b.x)+ (a.y-b.y)*(a.y-b.y));
}

ll po(ll a,ll b)
{
    if(b<=0)
        return 1;
    else if(b==1)
        return a;

    ll vl = po((a*a),b/2);
    if(b%2==0)
        return vl;
    else
        return (vl)*a;
}

ll pomod(ll a,ll b)
{
    a= a%mod;
    if(b<=0)
        return 1%mod;
    else if(b==1)
        return a%mod;

    ll vl = pomod((a*a)%mod,b/2);
    vl = vl%mod;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mod;
}

ll pomod(ll a,ll b,ll mo)
{
    a= a%mo;
    if(b<=0)
        return 1%mo;
    else if(b==1)
        return a%mo;

    ll vl = pomod((a*a)%mo,b/2);
    vl = vl%mo;
    if(b%2==0)
        return vl;
    else
        return ((vl)*a)%mo;
}
ll factmod(ll n, ll mo)
{
    ll val=n;
    ll ans =1;
    while(val>=1)
    {
        ans = (ans*val)%mo;
        val--;
    }

    return ans;
}
ll inv(ll a,ll mo)
{
    return pomod(a,mo-2,mo);
}

ll combinationMod(ll n, ll i)
{
    ll ans = 1;
    ans = (ans * factmod(n,mod))%mod;
    ll invVal =  (inv(factmod(i,mod),mod)%mod * inv(factmod(n-i,mod),mod)%mod)%mod;
    ans = (ans * invVal)%mod;
    return ans;
}

vector<vll> preComputeCombinationMod(int n)
{
    vector<vll> comb(n+1,vll(n+1,0));
    comb[0][0]=1;
    rep(i,1,n)
    {
        comb[i][0] = 1;
        comb[0][i] = 0;
    }

    rep(i,1,n)
    {
        rep(j,1,i)
        {
            comb[i][j] = (comb[i-1][j-1]%mod + comb[i-1][j]%mod)%mod;
        }
    }

    return comb;
}
ll floorlog2(ll n)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=2;
    }

    return h-1;
}
ll floorlog2(ll n,ll b)
{
    ll h = 0;
    ll p = 1;
    while(p<=n)
    {
        h++;
        p*=b;
    }

    return h-1;
}

class Trie {
    private:
    vector<Trie*> children;
    bool this_inserted = false;
public:
    /** Initialize your data structure here. */
    Trie() {
        children.resize(26,NULL);
        this_inserted = false;
    }

    /** Inserts a word into the trie. */
    void insert(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                cur->children[ind] = new Trie();

            }
            cur = cur->children[ind];
        }

        cur->this_inserted = true;
    }

    /** Returns if the word is in the trie. */
    bool search(string word) {
        Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return cur->this_inserted;

    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        string word = prefix ;

      Trie * cur = this;

        for(char c: word)
        {
            int ind = c-'a';
            if(cur->children[ind]==NULL)
            {
                return false;
            }
                cur = cur->children[ind];
        }

        return true;
    }
};

class FenwickTree
{
    public:
    vll BIT;

    FenwickTree(int n)
    {
        BIT.resize(n+1,0);
    }
    FenwickTree(vll a)
    {
        int n = a.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,a[i]);
        }
    }
    FenwickTree(vi a)
    {
        vll b(a.begin(),a.end());

        int n = b.size();

        BIT.resize(n+1,0);

        rep(i,0,n-1)
        {
            update(i+1,b[i]);
        }
    }

    void update(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        int x = ind;
        int sz = BIT.size();

        while(x<sz)
        {
            BIT[x]+=val;
            x += (x&-x);
        }
    }

    void set(int ind, ll val)
    {
        assert(0<=ind and ind<BIT.size());

        ll currentVal = query(ind,ind);
        update(ind,val-currentVal);
    }
    ll query(int l, int r)
    {
        assert(0<=l and r<BIT.size());

        if(r<l)
        {
            return 0;
        }
        else
            return prefQuery(r) - prefQuery(l-1);
    }
    ll prefQuery(int ind)
    {
        assert(0<=ind and ind<BIT.size());
        int x = ind;
        ll sum = 0;
        while(x>0)
        {
            sum+=BIT[x];
            x-=(x&-x);
        }

        return sum;
    }
};
vll getPrimes(ll highestNum){

    vb isPrime(highestNum+5,true);
    vll primes;
    rep(i,2,highestNum){
        if(isPrime[i])
        {   primes.push_back(i);
            ll j = i;
            while(j*i<=highestNum){
                isPrime[j*i]=false;
                j++;
            }
        }
    }
    return primes;
}
ll getMultiplicity(ll num, ll prime){
    ll mult = 0;
    while(num%prime==0){
        mult+=1;
        num/=prime;
    }
    return mult;
}
vll getPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vll multcities(sz,0);

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return multcities;
        else
        {
            multcities[i] = getMultiplicity(num,prime);
            ll di = po(prime,multcities[i]);
            num = num/di;
        }
    }
    return multcities;
}

map<ll,ll> getMapPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    map<ll,ll> primeFac;
    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            primeFac[prime] = getMultiplicity(num,prime);
            ll di = po(prime,primeFac[prime]);
            num = num/di;
        }
    }
    return primeFac;
}
vpll getListPrimeFactorization(ll num, vll &primes){
    int sz = primes.size();
    vpll primeFac;

    rep(i,0,sz-1)
    {
        ll prime = primes[i];
        if(prime>num)
           return primeFac;
        else
        {
            ll mult = getMultiplicity(num,prime);
            ll di = po(prime,mult);
            num = num/di;

            if(mult>0){
                primeFac.push_back(make_pair(prime,mult));
            }
        }
    }
    return primeFac;
}
vi compute_z(string s)
{
    int n = s.length();
    vi z(n,0);
    int l=0,r=0;
    z[0]=n;
    rep(i,1,n-1)
    {
        if(r<i)
        {
            l=r=i;
            int j = 0;
            if(s[0]!=s[i])
            {
                continue;
            }

            while(j<n and s[j] == s[i+j])
            {
                j++;
            }
            r = i+j-1;
            z[i] = r-i+1;
        }
        else
        {
            int beta = r-i+1;
            int k = i-l;

            if(z[k]<beta)
            {

                z[i]=z[k];

            }
            else
            {
                int j = 0;
                l = i;
                while(r<n and s[r]==s[r-l])
                {
                    r+=1;
                }
                r-=1;

                z[i] = r-i+1;

            }
        }
    }

    return z;
}

vi getOccurences(string s, string t){

     string comb = t + "$" + s;

     auto z_vals = compute_z(comb);

     int n = s.size();
     int t_sz = t.size();

     vi occ;

     rep(i,0,n-1)
     {
         if(z_vals[t_sz + 1 +  i]==t_sz){
             occ.push_back(i);
         }
     }
     return occ;
}

class DSU{
    private:
    vi parent;
    vi size;
    public:
    DSU(int n){
        parent.resize(n+5,0);
        size.resize(n+5,0);
        rep(i,1,n){
            parent[i]=i;
            size[i] = 1;
        }
    }
    vi getParents(){
        return parent;
    }
     vi getSizes(){
        return size;
    }
    int getRoot(int node){
       int par = parent[node];
       if(parent[par] == par){
           return par;
       }

       int root = getRoot(par);

       parent[node] = root;

       return root;
    }

    bool checkSame(int a, int b){
        return getRoot(a)==getRoot(b);
    }

    void connectNodes(int a, int b){
        int root1 = getRoot(a);
        int root2 = getRoot(b);

        if(size[root1] < size[root2]){
            swap(root1,root2);
        }

        parent[root2] = root1;
        size[root1] += size[root2];
    }
};

class SegmentTreeNode{
    private:

    ll total;
    ll pendingUpdate;

    public:
    int start,end;

    SegmentTreeNode(): total(0), start(-1),end(-1),pendingUpdate(0){}

    void assignLeaf(ll value, int start, int end){
        total = value;
        this->start = start;
        this->end = end;
    }
    void merge(SegmentTreeNode &left, SegmentTreeNode&right){
        this->start = left.start;
        this->end = right.end;
        ll leftTotal = left.getValue();
        ll rightTotal = right.getValue();

        if(left.ifPendingUpdate()){
            leftTotal += left.getSegmentSize() * left.getPendingUpdate();
        }

        if(right.ifPendingUpdate()){
            rightTotal += right.getSegmentSize() * right.getPendingUpdate();
        }
        this->total = leftTotal + rightTotal;

    }
    ll getValue(){
        return total;
    }

    ll getPendingUpdate(){
        return pendingUpdate;
    }
    bool ifPendingUpdate(){
        return pendingUpdate!=0;
    }

    void applyPendingUpdate(){
        this->total += (this->pendingUpdate) * (this->getSegmentSize());
        this->pendingUpdate = 0;
    }

    void addUpdate(ll val){
        this->pendingUpdate += val;
    }

    int getSegmentSize(){
        return (end-start + 1);
    }
};

class SegmentTree{

    public:
    int N;
    SegmentTree(vll &arr){

        this->N = arr.size();
        this-> treeSize = getSegmentTreeSize(this->N);
        //cout<<"N treeSize:" <<N<<" "<<treeSize<<"\n";
        nodes.resize(this->treeSize);

        this->buildTree(arr,1,0,N-1);
    }

     void updateRange(int startPos, int endPos, ll val){
         //flip all coins in [startPos,endPos]
         updateRange(1,startPos,endPos,val);
     }
    ll getValue(int startPos, int endPos){
        auto res = getValue(1,startPos,endPos);
        return res.getValue();
    }
    private:
     vector<SegmentTreeNode> nodes;

     int treeSize;

     void buildTree(vll &arr,int stIndex, int left, int right){
         if(left==right){
             this->nodes[stIndex].assignLeaf(arr[left],left,right);
             return;
         }

         int mid = (left+right)/2;
         int leftIndex = 2*stIndex,rightIndex = leftIndex+1;

         buildTree(arr,leftIndex,left,mid);
         buildTree(arr,rightIndex,mid+1,right);

         nodes[stIndex].merge(nodes[leftIndex],nodes[rightIndex]);
     }

    void updateRange(int stIndex, int startPos, int endPos, ll val){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            nodes[stIndex].addUpdate(val);
            return;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        if(endPos<=mid){
            updateRange(leftChildIndex,startPos,endPos,val);
        }else if(startPos>mid){
            updateRange(rightChildIndex,startPos,endPos,val);
        }else{
            updateRange(leftChildIndex,startPos,mid,val);
            updateRange(rightChildIndex,mid+1,endPos,val);
        }

        nodes[stIndex].merge(nodes[leftChildIndex],nodes[rightChildIndex]);
    }

    SegmentTreeNode getValue(int stIndex,int startPos, int endPos){
        if(startPos == nodes[stIndex].start and endPos == nodes[stIndex].end){
            auto result = nodes[stIndex];
            if(result.ifPendingUpdate())
                result.applyPendingUpdate();

            return result;
        }

        int mid = (nodes[stIndex].start + nodes[stIndex].end)/2;
        int leftChildIndex = 2*stIndex, rightChildIndex = leftChildIndex + 1;

        SegmentTreeNode result;

        if(endPos<=mid){
            result = getValue(leftChildIndex,startPos,endPos);
        }else if(startPos>mid){
            result = getValue(rightChildIndex,startPos,endPos);
        }else{
            auto leftResult = getValue(leftChildIndex,startPos,mid);
            auto rightResult = getValue(rightChildIndex,mid+1,endPos);

            result.merge(leftResult,rightResult);
        }

        if(nodes[stIndex].ifPendingUpdate()){
            result.addUpdate(nodes[stIndex].getPendingUpdate());
            result.applyPendingUpdate();
        }

        return result;
    }
     int getSegmentTreeSize(int N){
         int x = 1;
         while(x<N){
             x = x*2;
         }
         return x*2;
     }
};

int main(void)
{
    ios_base::sync_with_stdio(false);
    int n;
    cin>>n;
    vi a(n+5,0);
    vi prev(n,-1);
    vi nex(n,n);
    vector<bool> is_del(n,false);

    vi del_time(n+5,n+5);

    rep(i,1,n){
        cin>>a[i];
    }
    int ans = 0;
    rep(i,1,n){
        int bel_max = 0;
        bool isDel = false;
        int del_t = n+5;
        reprev(j,i-1,1){
            if(a[j]>a[i] and del_time[j]>bel_max){
                del_t = bel_max + 1;
                isDel = true;
                break;
            } else if(a[j]<a[i]){
                bel_max = max(bel_max,del_time[j]);
            }
        }
        del_time[i] = del_t;
        if(isDel){
            ans = max(ans,del_time[i]);
        }
    }
    cout<<ans;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define maxx 100002

int main()
{
	int n;
	cin>>n;

	int a[n];
	for (int i = 0; i < n; ++i)
	{
		cin>>a[i];
	}

	int l[n];
	l[0]=maxx;
	int ans=0;
	stack<int> s;
	s.push(0);

	for(int i=1;i<n;i++)
	{
		l[a[i]]=1;

		while(!s.empty() && a[i]>s.top())
		{
			l[a[i]]=max(l[i],l[s.top()]+1);
			s.pop();
		}
		s.push(a[i]);
	}

	for(int i=0;i<n;i++)
	{
		if(l[i]<maxx)
		{
			ans=max(ans,l[i]);
			// cout<<"i: "<<i<<endl;
			// cout<<"l[i]: "<<l[i]<<endl;
		}
	}
	cout<<ans<<endl;

}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define maxx 100002

int main()
{
	int n;
	cin>>n;

	int a[n];
	for (int i = 0; i < n; ++i)
	{
		cin>>a[i];
	}

	int l[n];
	l[0]=maxx;
	int ans=0;
	for(int i=1;i<n;i++)
	{
		if(a[i]<a[i-1])
		{
			l[i]=1;
		}
		else
		{
			l[i]=l[i-1]+1;
		}
	}

	for(int i=0;i<n;i++)
	{
		if(l[i]<maxx)
		{
			ans=max(ans,l[i]);
		}
	}
	cout<<ans<<endl;

}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define maxx 100002

int main()
{
	int n;
	cin>>n;

	int a[n];
	for (int i = 0; i < n; ++i)
	{
		cin>>a[i];
	}

	int l[n];
	l[0]=maxx;
	int ans=0;
	stack<int> s;
	s.push(0);

	for(int i=1;i<n;i++)
	{
		l[a[i]]=1;

		while(!s.empty() && a[i]>s.top())
		{
			l[a[i]]=max(l[a[i]],l[s.top()]+1);
			s.pop();
		}
		s.push(a[i]);
	}

	for(int i=0;i<n;i++)
	{
		if(l[i]<maxx)
		{
			ans=max(ans,l[i]);
			// cout<<"i: "<<i<<endl;
			// cout<<"l[i]: "<<l[i]<<endl;
		}
	}
	cout<<ans<<endl;

}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define maxx 100002

int main()
{
	int n;
	cin>>n;

	int a[n];
	for (int i = 0; i < n; ++i)
	{
		cin>>a[i];
	}

	int l[n];
	l[a[0]]=maxx;
	int ans=0;
	stack<int> s;
	s.push(a[0]);

	for(int i=1;i<n;i++)
	{
		l[a[i]]=1;

		while(!s.empty() && a[i]>s.top())
		{
			l[a[i]]=max(l[a[i]],l[s.top()]+1);
			s.pop();
		}
		s.push(a[i]);
	}

	for(int i=0;i<n;i++)
	{
		if(l[i]<maxx)
		{
			ans=max(ans,l[i]);
			// cout<<"i: "<<i<<endl;
			// cout<<"l[i]: "<<l[i]<<endl;
		}
	}
	cout<<ans<<endl;

}


#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define maxx 100002

int main()
{
	int n;
	cin>>n;

	int a[n];
	for (int i = 0; i < n; ++i)
	{
		cin>>a[i];
	}

	int l[n+1];
	l[a[0]]=maxx;
	int ans=0;
	stack<int> s;
	s.push(a[0]);

	for(int i=1;i<n;i++)
	{
		l[a[i]]=1;

		while(!s.empty() && a[i]>s.top())
		{
			l[a[i]]=max(l[a[i]],l[s.top()]+1);
			s.pop();
		}
		s.push(a[i]);
	}

	for(int i=1;i<=n;i++)
	{
		if(l[i]<maxx)
		{
			ans=max(ans,l[i]);
			// cout<<"i: "<<i<<endl;
			// cout<<"l[i]: "<<l[i]<<endl;
		}
	}
	cout<<ans<<endl;

}


#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <cassert>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

const int INF = 0x3f3f3f3f;

int dfs(int cur, const vector<int>& ks, vector<int>& step) {
    if (ks[cur] == -1) {
        return 0;
    }

    if (step[cur] != -1) {
        return step[cur];
    }

    return step[cur] = dfs(ks[cur], ks, step) + 1;
}

int main() {
    int n;
    input(n);
    vector<int> ns(n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &ns[i]);
    }

    vector<int> ks(n, -1);
    vector<int> step(n, 0);

    for (int i = 1; i < n; i++) {
        bool flag = true;
        int cur = i - 1;
        int maxi = 0;
        while (cur >= 0 && ns[cur] < ns[i]) {
            if (ks[cur] == -1) {
                flag = false;
                break;
            }
            maxi = max(maxi, step[cur]);
            cur = ks[cur];
        }
        if (flag) {
            step[i] = maxi + 1;
        }
        ks[i] = cur;
    }

    int ans = 0;
    for (int i = 1; i < n; i++) {
        // printf("%d\n", step[i]);
        ans = max(ans, step[i]);
    }
    print(ans);

    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <cassert>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

const int INF = 0x3f3f3f3f;

int dfs(int cur, const vector<int>& ks, vector<int>& step) {
    if (ks[cur] == -1) {
        return 0;
    }

    if (step[cur] != -1) {
        return step[cur];
    }

    return step[cur] = dfs(ks[cur], ks, step) + 1;
}

int main() {
    int n;
    input(n);
    vector<int> ns(n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &ns[i]);
    }

    vector<int> ks(n, -1);
    vector<int> step(n, 0);

    for (int i = 1; i < n; i++) {
        int cur = i - 1;
        int m = 0;
        while (true) {
            if (cur == -1) {
                break;
            } else if (cur == 0) {
                if (ns[0] > ns[i]) {
                    ks[i] = 0;
                    step[i] = m;
                }
                break;
            } else if (ns[cur] > ns[i]) {
                assert(0 <= cur && cur < n);
                ks[i] = ks[cur];
                step[i] = m + 1;
                break;
            } else {
                assert(0 <= cur && cur < n);
                m = step[cur] + 1;
                cur = ks[cur];
            }
        }
    }

    int ans = 0;
    for (int i = 1; i < n; i++) {
        // printf("%d\n", step[i]);
        ans = max(ans, step[i]);
    }
    print(ans);

    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

const int INF = 0x3f3f3f3f;

int dfs(int cur, const vector<int>& ks, vector<int>& step) {
    if (ks[cur] == -1) {
        return 0;
    }

    if (step[cur] != -1) {
        return step[cur];
    }

    return step[cur] = dfs(ks[cur], ks, step) + 1;
}

int main() {
    int n;
    input(n);
    vector<int> ns(n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &ns[i]);
    }

    vector<int> ks(n, -1);
    vector<int> step(n, 0);

    for (int i = 1; i < n; i++) {
        int cur = i - 1;
        int m = 0;
        while (true) {
            if (cur == 0) {
                if (ns[0] > ns[i]) {
                    ks[i] = 0;
                    step[i] = m;
                }
                break;
            } else if (ns[cur] > ns[i]) {
                ks[i] = ks[cur];
                step[i] = m + 1;
                break;
            } else {
                m = step[cur] + 1;
                cur = ks[cur];
            }
        }
    }

    int ans = 0;
    for (int i = 1; i < n; i++) {
        // printf("%d\n", step[i]);
        ans = max(ans, step[i]);
    }
    print(ans);

    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

int main() {
    int n;
    input(n);
    vector<int> ns(n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &ns[i]);
    }

    map<int, list<pair<int, int> >::iterator> mp;
    list<pair<int, int> > lst;

    for (int i = 0; i < n; i++) {
        lst.push_back({i, ns[i]});
        mp[ns[i]] = prev(lst.end());
    }

    int ans = 0;
    for (auto p: mp) {
        auto iter = p.second;
        if (iter == lst.begin()) {
            continue;
        }
        auto jter = prev(iter);

        if (iter->second < jter->second) {
            ans = max(ans, iter->first - jter->first);
        }
        lst.erase(iter);
    }
    print(ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
#define ll long long int
//#define d double
#define F first
#define S second
#define FastIO ios_base::sync_with_stdio(false),cin.tie(0)
#define fix std::fixed<<setprecision(10)
const int M=1e9+7;
#define f(n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define vi vector<int>
#define pb push_back
#define si set<int>
#define cl(n,m) (ceil(double(n)/double(m)))
#define T() int t; cin>>t; while(t--)
#define pi pair<ll,ll>
//const int MOD=998244353;
const int MOD=1e6+7;
#define endl "\n"
const double PI = 3.141592653589793238460;
#define READ(f) freopen(f, "r", stdin)
#define WRITE(f) freopen(f, "w", stdout)
//bitset<N>bs;
//bitset<512>bb[512];
//vector<vector<int>>arr;

ll power(ll a,ll b)
{
    ll res=1;
    if(a==0)return 0;
    if(a==1)return 1;
    for(;b>0;b>>=1)
    {
        if(b&1)res=(res*a);
        if(res>MOD)res%=MOD;
        a=(a*a);
        if(a>MOD)a=a%MOD;
    }
    return res;
}

bool isPrime[1000001];
vector<ll>prime;

void seive(int limit)
{
    isPrime[0]=isPrime[1]=1;

    for(int i=2;i*i<=limit;i++)
    {
        if(!isPrime[i])
        for(int j=i*i;j<=limit;j+=i)
        {
            isPrime[j]=1;
        }
    }
    for(int i=2;i<=limit;i++)if(!isPrime[i])prime.pb(i);
}

int main()
{
    int n;
    cin>>n;
    vector<int>v;
    v.pb(0);
    int x;
    f(n){
    cin>>x;
    v.pb(x);
    }
    int ans=0;

    int life[n+1]{0};
    life[0]=1000000;
    stack<int>killer;
    killer.push(0);
    for(int i=1;i<=n;i++)
    {
        life[i]=1;

        while(killer.size() && v[i]>v[killer.top()])
        {
            life[i]=max(life[i],life[killer.top()]+1);
            killer.pop();
        }
        killer.push(i);
    }

    for(int i=1;i<=n;i++)if(life[i]<1e6)ans=max(ans,life[i]);
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
#define ll long long int
//#define d double
#define F first
#define S second
#define FastIO ios_base::sync_with_stdio(false),cin.tie(0)
#define fix std::fixed<<setprecision(10)
const int M=1e9+7;
#define f(n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define vi vector<int>
#define pb push_back
#define si set<int>
#define cl(n,m) (ceil(double(n)/double(m)))
#define T() int t; cin>>t; while(t--)
#define pi pair<ll,ll>
//const int MOD=998244353;
const int MOD=1e6+7;
#define endl "\n"
const double PI = 3.141592653589793238460;
#define READ(f) freopen(f, "r", stdin)
#define WRITE(f) freopen(f, "w", stdout)
//bitset<N>bs;
//bitset<512>bb[512];
//vector<vector<int>>arr;

ll power(ll a,ll b)
{
    ll res=1;
    if(a==0)return 0;
    if(a==1)return 1;
    for(;b>0;b>>=1)
    {
        if(b&1)res=(res*a);
        if(res>MOD)res%=MOD;
        a=(a*a);
        if(a>MOD)a=a%MOD;
    }
    return res;
}

bool isPrime[1000001];
vector<ll>prime;

void seive(int limit)
{
    isPrime[0]=isPrime[1]=1;

    for(int i=2;i*i<=limit;i++)
    {
        if(!isPrime[i])
        for(int j=i*i;j<=limit;j+=i)
        {
            isPrime[j]=1;
        }
    }
    for(int i=2;i<=limit;i++)if(!isPrime[i])prime.pb(i);
}

int main()
{
    int n;
    cin>>n;
    vector<int>v;
    int x;
    f(n){
    cin>>x;
    v.pb(x);
    }
    int ans=0;
    while(1)
    {
        n=v.size();

        vector<int>v2;
        v2.pb(v[0]);
        int cnt=0;
        for(int i=1;i<n-1;i++)
        {
            if(v[i]>v[i-1] && v[i]>v[i+1])
                v2.pb(v[i]),cnt++;
        }

        if(n>1 && v[n-2]<v[n-1])
        {
            v.pb(v[n-1]);
        }
        else if(n>1)cnt++;
        if(cnt)ans++;
        else break;
        v=v2;
    }
    cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
#define ll long long int
//#define d double
#define F first
#define S second
#define FastIO ios_base::sync_with_stdio(false),cin.tie(0)
#define fix std::fixed<<setprecision(10)
const int M=1e9+7;
#define f(n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define vi vector<int>
#define pb push_back
#define si set<int>
#define cl(n,m) (ceil(double(n)/double(m)))
#define T() int t; cin>>t; while(t--)
#define pi pair<ll,ll>
const int MOD=998244353;
#define endl "\n"
const double PI = 3.141592653589793238460;
//bitset<N>bs;
//bitset<512>bb[512];
//vector<vector<int>>arr;

ll power(ll a,ll b)
{
    ll res=1;
    if(a==0)return 0;
    if(a==1)return 1;
    for(;b>0;b>>=1)
    {
        if(b&1)res=(res*a);
        if(res>MOD)res%=MOD;
        a=(a*a);
        if(a>MOD)a=a%MOD;
    }
    return res;
}

bool isPrime[1000100];
vector<int>prime;

void seive()
{
    isPrime[0]=isPrime[1]=1;

    for(int i=2;i*i<=1000000;i++)
    {
        if(!isPrime[i])
        for(int j=i*i;j<=1000000;j+=i)
        {
            isPrime[j]=1;
        }
    }
    for(int i=2;i<=1000000;i++)if(!isPrime[i])prime.pb(i);
}

bool isPalindrome(string &temp)
{
    int mid=temp.length()/2;
    mid++;
    int j;
    int n=temp.length();
    for(int i=0,j=n-1;i<n&&j>=0;i++,j--)
    {
        if(temp[i]!=temp[j])return false;
    }
    return true;
}

int main()
{
    int n;
    cin>>n;
    vector<int>a(n);
    f(n)cin>>a[i];
    int cnt=0;
    while(1)
    {
        int i=0;
        vector<int>a2;
        bool flag=false;
        while(i+1<n){
            a2.pb(a[i]);
        while(i+1<n && a[i]>a[i+1])
        {
            i++;
            flag=1;
        }
        i++;
        }
        if(flag)cnt++;
        else break;
        if(i<n)a2.pb(a[i]);
        a=a2;
        n=a.size();
//
//        f(n)cout<<a2[i]<<' ';
//        cout<<endl;
        if(n<=1)break;
    }
    cout<<cnt;

}


#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
#define ll long long int
//#define d double
#define F first
#define S second
#define FastIO ios_base::sync_with_stdio(false),cin.tie(0)
#define fix std::fixed<<setprecision(10)
const int M=1e9+7;
#define f(n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define vi vector<int>
#define pb push_back
#define si set<int>
#define cl(n,m) (ceil(double(n)/double(m)))
#define T() int t; cin>>t; while(t--)
#define pi pair<ll,ll>
const int MOD=998244353;
#define endl "\n"
const double PI = 3.141592653589793238460;
//bitset<N>bs;
//bitset<512>bb[512];
//vector<vector<int>>arr;

ll power(ll a,ll b)
{
    ll res=1;
    if(a==0)return 0;
    if(a==1)return 1;
    for(;b>0;b>>=1)
    {
        if(b&1)res=(res*a);
        if(res>MOD)res%=MOD;
        a=(a*a);
        if(a>MOD)a=a%MOD;
    }
    return res;
}

bool isPrime[1000100];
vector<int>prime;

void seive()
{
    isPrime[0]=isPrime[1]=1;

    for(int i=2;i*i<=1000000;i++)
    {
        if(!isPrime[i])
        for(int j=i*i;j<=1000000;j+=i)
        {
            isPrime[j]=1;
        }
    }
    for(int i=2;i<=1000000;i++)if(!isPrime[i])prime.pb(i);
}

bool isPalindrome(string &temp)
{
    int mid=temp.length()/2;
    mid++;
    int j;
    int n=temp.length();
    for(int i=0,j=n-1;i<n&&j>=0;i++,j--)
    {
        if(temp[i]!=temp[j])return false;
    }
    return true;
}

int main()
{
    int n;
    cin>>n;
    vector<int>a(n);
    f(n)cin>>a[i];
    int cnt=0;
    while(1)
    {
        int i=0;
        vector<int>a2;
        bool flag=false;
        while(i+1<n){
            a2.pb(a[i]);
        while(i+1<n && a[i]>a[i+1])
        {
            i++;
            flag=1;
        }
        i++;
        }
        if(flag)cnt++;
        else break;
        if(i<n)a2.pb(i);
        a=a2;
        n=a.size();
//
//        f(n)cout<<a2[i]<<' ';
//        cout<<endl;
        if(n<=1)break;
    }
    cout<<cnt;

}


#include<bits/stdc++.h>
#define god dimasi5eks
#pragma GCC optimize("O3")
#define fi first
#define se second
#define pb push_back
#define pf push_front
#define mod 1000000007
#define eps 1e-9

using namespace std;

typedef long long ll;

int n, v[100002], ans[100002];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    for(int i = 1; i <= n; ++i)
        cin >> v[i];
    deque<int> mx;
    int ansmx = 0;
    for(int i = 1; i <= n; ++i)
    {
        while(!mx.empty() && v[i] > v[mx.back()])
            mx.pop_back();
        if(mx.empty())
            ans[i] = 0;
        else
        {
            if(mx.back() == i-1)
                ans[i] = 1;
            else
                ans[i] = ans[i-1] + 1;
        }
        ansmx = max(ansmx, ans[i]);
        mx.push_back(i);
    }
    cout << ansmx;
    return 0;
}


#include<bits/stdc++.h>
#define god dimasi5eks
#pragma GCC optimize("O3")
#define fi first
#define se second
#define pb push_back
#define pf push_front
#define mod 1000000007
#define eps 1e-9

using namespace std;

typedef long long ll;

int n, v[100002], ans[100002];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    for(int i = 1; i <= n; ++i)
        cin >> v[i];
    deque<int> mx;
    int ansmx = 0;
    for(int i = 1; i <= n; ++i)
    {
        while(!mx.empty() && v[i] > v[mx.back()])
            mx.pop_back();
        if(mx.empty())
            ans[i] = 0;
        else
        {
            if(mx.back() == i-1)
                ans[i] = 1;
            else
                ans[i] = ans[mx.back()] + 1;
        }
        ansmx = max(ansmx, ans[i]);
        mx.push_back(i);
    }
    cout << ansmx;
    return 0;
}


#include<bits/stdc++.h>
#define god dimasi5eks
#pragma GCC optimize("O3")
#define fi first
#define se second
#define pb push_back
#define pf push_front
#define mod 1000000007
#define eps 1e-9

using namespace std;

typedef long long ll;

int n, v[100002], ans[100002];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    for(int i = 1; i <= n; ++i)
        cin >> v[i];
    /*
    deque<int> mx;
    for(int i = 1; i <= n; ++i)
    {
        while(!mx.empty() && v[i] > v[mx.back()])
            mx.pop_back();
        if(mx.empty())
            ans[i] = 0;
        else
        {
            if(mx.back() == i-1)
                ans[i] = 1;
            else
                ans[i] = ans[i-1] + 1;
        }
        ansmx = max(ansmx, ans[i]);
        mx.push_back(i);
    }
    cout << ansmx << '\n';
    */
    int ansmx = 0;
    bool ok = 1;
    vector<int> vx;
    for(int i = 1; i <= n; ++i)
        vx.pb(v[i]);
    vector<int> v2;
    while(ok)
    {
        ok = 0;
        v2.clear();
        for(int i = 0; i < vx.size(); ++i)
        {
            if(i == 0 || vx[i] > vx[i-1])
                v2.pb(vx[i]);
            else
                ok = 1;
        }
        vx = v2;
        if(ok == 1)
            ++ansmx;
    }
    cout << ansmx << '\n';
    return 0;
}


#include<bits/stdc++.h>
#define god dimasi5eks
#pragma GCC optimize("O3")
#define fi first
#define se second
#define pb push_back
#define pf push_front
#define mod 1000000007
#define eps 1e-9

using namespace std;

typedef long long ll;

int n, v[100002], ans[100002], ansmx;

int rungg()
{
    ansmx = 0;
    set<int> s;
    set<int> lft;
    for(int i = 2; i <= n; ++i)
        if(v[i] < v[i-1])
            s.insert(i);
        else
            lft.insert(i);
    while(!s.empty())
    {
        set<int> s2;
        ++ansmx;
        while(!s.empty())
        {
            int val = *s.rbegin();
            s.erase(val);
            int nxt = n+1;
          //  cout << ansmx << " " << val << '\n';
            set<int> ::iterator it = lft.lower_bound(val);
            if(it != lft.end())
            {
                nxt = *lft.lower_bound(val);
                if(it != lft.begin())
                {
                    --it;
             //       cout << *it << " " << nxt << " " << val << " " << v[*it] << " " << v[nxt] << '\n';
                    if(v[*it] > v[nxt])
                        s2.insert(nxt);
                }
            }
        }
        s = s2;
        while(!s2.empty())
        {
            lft.erase(*s2.rbegin());
            s2.erase(*s2.rbegin());
        }
    }
    return ansmx;
}
int runbrut()
{
    ansmx = 0;
    bool ok = 1;
    vector<int> vx;
    for(int i = 1; i <= n; ++i)
        vx.pb(v[i]);
    vector<int> v2;
    while(ok)
    {
        ok = 0;
        v2.clear();
        for(int i = 0; i < vx.size(); ++i)
        {
            if(i == 0 || vx[i] > vx[i-1])
                v2.pb(vx[i]);
            else
                ok = 1;
        }
        vx = v2;
        if(ok == 1)
            ++ansmx;
    }
    return ansmx;
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    for(int i = 1; i <= n; ++i)
        cin >> v[i];
    cout << rungg() << '\n';
    return 0;
    while(1)
    {
        n = rand() % 10 + 1;
        for(int i = 1; i <= n; ++i)
            v[i] = i;
        for(int i = 1; i <= n; ++i)
            random_shuffle(v+1, v+n+1);
        int vvv = rungg();
        int zzz = runbrut();
        if(vvv != zzz)
        {
            cout << n << '\n';
            for(int i = 1; i <= n; ++i)
                cout << v[i] << " ";
            cout << '\n';
            cout << vvv << " " << zzz << '\n';
            return 0;
        }
    }
    return 0;
}