#include <bits/stdc++.h>
using namespace std;
const long long MX = 50010;
long long n = 0;
long long a[MX] = {0};
struct node
{
long long lc, rc;
long long maxn;
} tree[MX << 2];
long long root, cnt;
inline void add_node(long long now, long long val)
{
tree[now].maxn = max(tree[now].maxn, val);
}
inline void update(long long now)
{
tree[now].maxn = max(tree[tree[now].lc].maxn, tree[tree[now].rc].maxn);
}
void add(long long now, long long l, long long lt, long long rt, long long val)
{
if (lt > l || l > rt)
return;
if (lt == rt)
{
add_node(now, val);
return;
}
long long mid = (lt + rt - 1) >> 1;
add(tree[now].lc, l, lt, mid, val);
add(tree[now].rc, l, mid + 1, rt, val);
update(now);
}
long long searc(long long now, long long l, long long r, long long lt, long long rt)
{
if (lt > r || l > rt)
return -0x3f3f3f3f;
if (l <= lt && rt <= r)
{
return tree[now].maxn;
}
long long mid = (lt + rt - 1) >> 1;
return max(searc(tree[now].lc, l, r, lt, mid), searc(tree[now].rc, l, r, mid + 1, rt));
}
void build_tree(long long &now, long long lt, long long rt)
{
if (!now)
now = ++cnt;
if (lt == rt)
{
tree[now].maxn = 1;
return;
}
int mid = (lt + rt - 1) >> 1;
build_tree(tree[now].lc, lt, mid);
build_tree(tree[now].rc, mid + 1, rt);
update(now);
}
long long dp1[MX] = {0};
long long dp2[MX] = {0};
signed main()
{
long long x;
long long maxi = 0;
while (cin >> x)
a[++n] = x, maxi = max(maxi, x);
for (long long i = 1; i <= n; i++)
dp1[i] = dp2[i] = 1;
build_tree(root, 1, maxi);
long long maxj = 0;
for (long long i = 1; i <= n; i++)
{
dp1[i] = max(dp1[i], searc(root, a[i], maxi, 1, maxi) + 1);
maxj = max(maxj, dp1[i]);
add(root, a[i], 1, maxi, dp1[i]);
}
cout << maxj - 1 << endl;
maxj = 0;
build_tree(root, 1, maxi);
for (long long i = 1; i <= n; i++)
{
dp2[i] = searc(root, 1, a[i] - 1, 1, maxi) + 1;
maxj = max(maxj, dp2[i]);
add(root, a[i], 1, maxi, dp2[i]);
}
cout << maxj - 1;
return 0;
}