#include<bits/stdc++.h>
// #include<ext/pb_ds/assoc_container.hpp>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back
#define x first
#define y second
#define mkp make_pair
#define show(x) cout << (#x) << ": " << x << endl

using namespace std;
// using namespace __gnu_pbds;

using ll = long long;
using pii = pair<int, int>;
using pli = pair<ll, int>;
using pil = pair<int, ll>;
template<typename T> using Array = vector<T>;
template<typename T> using Matrix = Array<Array<T>>;
using Graph = Matrix<int>;

// template<typename T> using Set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<typename T> bool relax(T& r, const T& x) {
    if (x < r) {
        r = x;
        return true;
    }
    return false;
}

template<typename T> bool heavy(T& h, const T& x) {
    if (h < x) {
        h = x;
        return true;
    }
    return false;
}

const int DX[8] = {-1, +1, +0, +0, +1, -1, +1, -1};
const int DY[8] = {+0, +0, -1, +1, +1, -1, -1, +1};

/************************************************************
* find_by_order(k) = iterator to (k)-th greatest element    *
* order_of_key(k) = counts number of strictly less elements *
*************************************************************/

vector<pii> parse(int n) {
    vector<int> a(n);
    for (int& x : a)
        cin >> x;
    map<int, int> id;
    int cnt = 0;
    vector<pii> res;
    for (int i = 0; i < n; i++) {
        if (id.find(a[i]) == id.end())
            id[a[i]] = cnt++;
        int j = i;
        while (j < n && a[j] == a[i])
            j++;
        j--;
        res.pb(mkp(j - i + 1, id[a[i]]));
        i = j;
    }
    return res;
}

struct Tuple {
    int size;
    int type;
    int pos;

    Tuple(int size, int type, int pos) : size(size), type(type), pos(pos) {

    }

    Tuple() {
        Tuple(-1, -1, -1);
    }

    bool operator ==(const Tuple& other) {
        return (size == other.size && type == other.type && pos == other.pos);
    }
};

const Tuple EMPTY(-1, -1, -1);

struct SegmentTree {
    int n;
    vector<pii> mx;

    SegmentTree(vector<pii>& res) : n(SZ(res)) {
        mx.resize(n << 2);
        build(res, 0, 0, n);
    }

    void build(vector<pii>& res, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = res[l];
            return;
        }
        int m = (l + r) >> 1, lc = u + u + 1, rc = lc + 1;
        build(res, lc, l, m);
        build(res, rc, m, r);
        gather(u);
    }

    void gather(int u) {
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    pii combine(pii l, pii r) {
        return (l.x >= r.x ? l : r);
    }

    bool works() {
        if (mx[0].x == 0)
            return false;
        int pos = get(0, 0, n);
        auto l = get(0, pos, false, 0, 0, n);
        auto r = get(pos + 1, n, true, 0, 0, n);
        nullify(pos);
        if (l.type == r.type) {
            modify(l.pos, mkp(l.size + r.size, l.type));
            nullify(r.pos);
        }
        return true;
    }

    void nullify(int pos) {
        modify(pos, mkp(0, -1));
    }

    void modify(int pos, pii value) {
        modify(pos, value, 0, 0, n);
    }

    void modify(int pos, pii value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = value;
            return;
        }
        int m = (l + r) >> 1;
        if (pos < m)
            modify(pos, value, u + u + 1, l, m);
        else
            modify(pos, value, u + u + 2, m, r);
        gather(u);
    }

    Tuple get(int l, int r, bool tag, int u, int ul, int ur) {
        if (l >= ur || ul >= r)
            return EMPTY;
        if (ur - ul == 1)
            return Tuple(mx[u].x, mx[u].y, ul);
        auto res = EMPTY;
        int um = (ul + ur) >> 1, lc = u + u + 1, rc = lc + 1;
        if (tag) {
            if (mx[lc].x)
                res = get(l, r, tag, lc, ul, um);
            if (res == EMPTY && mx[rc].x)
                res = get(l, r, tag, rc, um, ur);
        } else {
            if (mx[rc].x)
                res = get(l, r, tag, rc, um, ur);
            if (res == EMPTY && mx[lc].x)
                res = get(l, r, tag, lc, ul, um);
        }
        return res;
    }

    int get(int u, int l, int r) {
        if (r - l == 1)
            return l;
        int res = -1;
        int m = (l + r) >> 1, lc = u + u + 1, rc = lc + 1;
        if (mx[lc].x >= mx[rc].x)
            res = get(lc, l, m);
        else
            res = get(rc, m, r);
        return res;
    }
};

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    auto res = parse(n);
    SegmentTree tree(res);
    int ans = 0;
    while (tree.works())
        ans++;
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

pii combine(pii a, pii b) {
    return (a.first != b.first ? (a.first > b.first ? a : b) : (a.second < b.second ? a : b));
}

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 1]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        if (pos < m)
            modify(pos, value, u + u + 1, l, m);
        else
            modify(pos, value, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

void assign(vector<int>& a, vector<int>& sz, vector<int>& low, vector<int>& up, vector<int>& srcId) {
    int n = SZ(a), id = 0;
    for (int i = 0; i < n; i++, id++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz[id]++;
            srcId[j] = id;
            j++;
        }
        j--;
        low.pb(i);
        up.pb(j);
        i = j;
    }
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, low, up, srcId(n);
    for (int& x : a)
        cin >> x;
    assign(a, sz, low, up, srcId);
    MaxSegmentTree tree(sz);
    int ans = 0;
    int id;
    while ((id = tree.get()) != -1) {
        ans++;
        int l = low[id];
        int r = up[id];
        assert(l != -1 && r != -1);
        tree.modify(id);
        if (!l || r == n - 1)
            continue;
        int x = l - 1;
        int y = r + 1;
        if (a[x] == a[y]) {
            int u = srcId[x];
            int v = srcId[y];
            tree.modify(u);
            tree.modify(v);
            sz[v] = 0;
            sz[u] += sz[v];
            tree.modify(u, sz[u]);
            up[u] = up[v];
            assert(u < v);
            low[v] = up[v] = -1;
        }
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back
#define fi first
#define se second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

struct cmp {
    bool operator()(const pii& lhs, const pii& rhs) {
        return (lhs.fi != rhs.fi ? lhs.fi > rhs.fi : lhs.se < rhs.se);
    }
};

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int& x : a)
        cin >> x;
    vector<int> dsu(n);
    vector<int> sz(n);
    vector<int> low(n);
    vector<int> up(n);
    set<pii, cmp> s;
    for (int u = 0; u < n; u++) {
        s.insert({sz[u] = 1, dsu[u] = u});
        low[u] = up[u] = u;
    }
    function<int(int)> get = [&](int u) {
        return (dsu[u] == u ? u : dsu[u] = get(dsu[u]));
    };

    auto unite = [&](int x, int y) {
        x = get(x);
        y = get(y);

        if (x == y)
            return;
        if (sz[x] > sz[y])
            swap(x, y);
        low[x] = min(low[x], low[y]);
        up[x] = max(up[x], up[y]);
        s.erase({sz[y], y});
        s.erase({sz[x], x});
        s.insert({sz[x] += sz[y], x});
        dsu[y] = x;
    };

    for (int u = 0; u < n - 1; u++)
        if (a[u] == a[u + 1])
            unite(u, u + 1);
    int ans = 0;
    while (!s.empty()) {
        int x = s.begin()->se;
        s.erase(s.begin());
        ans++;

        int l = low[x];
        int r = up[x];

        if (l)
            up[get(l - 1)] = up[x];
        else if (r + 1 < n)
            low[get(r + 1)] = low[x];
        if (!l || r == n - 1)
            continue;
        int u = get(l - 1);
        int v = get(r + 1);
        if (a[u] == a[v])
            unite(u, v);
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back
#define fi first
#define se second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

struct cmp {
    bool operator()(const pii& lhs, const pii& rhs) {
        return (lhs.fi != rhs.fi ? lhs.fi > rhs.fi : lhs.se < rhs.se);
    }
};

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int& x : a)
        cin >> x;
    vector<int> dsu(n);
    vector<int> sz(n);
    vector<int> low(n);
    vector<int> up(n);
    set<pii, cmp> s;
    for (int u = 0; u < n; u++) {
        s.insert({sz[u] = 1, dsu[u] = u});
        low[u] = up[u] = u;
    }
    function<int(int)> get = [&](int u) {
        return (dsu[u] == u ? u : dsu[u] = get(dsu[u]));
    };

    vector<bool> was(n);
    function<void(int, int)> unite = [&](int x, int y) {
        x = get(x);
        y = get(y);

        if (x == y)
            return;
        if (sz[x] > sz[y])
            swap(x, y);
        low[x] = min(low[x], low[y]);
        up[x] = max(up[x], up[y]);
        s.erase({sz[y], y});
        s.erase({sz[x], x});
        s.insert({sz[x] += sz[y], x});
        dsu[y] = x;
        was[y] = true;
    };
    for (int u = 0; u < n - 1; u++)
        if (a[u] == a[u + 1])
            unite(u, u + 1);
    int ans = 0;
    while (!s.empty()) {
        int x = s.begin()->se;
        s.erase(s.begin());
        ans++;

        int l = low[x];
        int r = up[x];

        if (!l || r == n - 1)
            continue;
        int u = get(l - 1);
        int v = get(r + 1);
        if (a[u] == a[v] && !was[u] && !was[v])
            unite(u, v);
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back
#define fi first
#define se second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

struct cmp {
    bool operator()(const pii& lhs, const pii& rhs) {
        return (lhs.fi != rhs.fi ? lhs.fi > rhs.fi : lhs.se < rhs.se);
    }
};

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int& x : a)
        cin >> x;
    vector<int> dsu(n);
    vector<int> sz(n);
    vector<int> low(n);
    vector<int> up(n);
    set<pii, cmp> s;
    for (int u = 0; u < n; u++) {
        s.insert({sz[u] = 1, dsu[u] = u});
        low[u] = up[u] = u;
    }
    function<int(int)> get = [&](int u) {
        return (dsu[u] == u ? u : dsu[u] = get(dsu[u]));
    };

    vector<bool> was(n);
    function<void(int, int)> unite = [&](int x, int y) {
        x = get(x);
        y = get(y);

        if (x == y)
            return;
        if (sz[x] > sz[y])
            swap(x, y);
        low[x] = min(low[x], low[y]);
        up[x] = max(up[x], up[y]);
        s.erase({sz[y], y});
        s.erase({sz[x], x});
        s.insert({sz[x] += sz[y], x});
        dsu[y] = x;
        was[y] = true;
    };
    for (int u = 0; u < n - 1; u++)
        if (a[u] == a[u + 1])
            unite(u, u + 1);
    int ans = 0;
    while (!s.empty()) {
        int x = s.begin()->se;
        s.erase(s.begin());
        ans++;
        was[x] = true;
        int l = low[x];
        int r = up[x];

        if (!l || r == n - 1)
            continue;
        int u = get(l - 1);
        int v = get(r + 1);
        if (a[u] == a[v] && !was[u] && !was[v])
            unite(u, v);
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

pii combine(pii a, pii b) {
    return (a.first != b.first ? (a.first > b.first ? a : b) : (a.second < b.second ? a : b));
}

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        (pos < m) ? modify(pos, value, u + u + 1, l, m) : modify(pos, value, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

void assign(vector<int>& a, vector<int>& sz, vector<int>& low, vector<int>& up, vector<int>& srcId) {
    int n = SZ(a), id = 0;
    for (int i = 0; i < n; i++, id++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz[id]++;
            srcId[j] = id;
            j++;
        }
        j--;
        low.pb(i);
        up.pb(j);
        i = j;
    }
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, low, up, srcId(n);
    for (int& x : a)
        cin >> x;
    assign(a, sz, low, up, srcId);
    MaxSegmentTree tree(sz);
    int ans = 0;
    int id;
    while ((id = tree.get()) != -1) {
        ans++;
        int l = low[id];
        int r = up[id];
        assert(l != -1 && r != -1);
        tree.modify(id);
        if (!l || r == n - 1)
            continue;
        int x = l - 1;
        int y = r + 1;
        if (a[x] == a[y]) {
            int u = srcId[x];
            int v = srcId[y];
            tree.modify(u);
            tree.modify(v);
            sz[v] = 0;
            sz[u] += sz[v];
            tree.modify(u, sz[u]);
            up[u] = up[v];
        }
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

pii combine(pii a, pii b) {
    return (a.first != b.first ? (a.first > b.first ? a : b) : (a.second < b.second ? a : b));
}

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 1]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        if (pos < m)
            modify(pos, value, u + u + 1, l, m);
        else
            modify(pos, value, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

void assign(vector<int>& a, vector<int>& sz, vector<int>& low, vector<int>& up, vector<int>& srcId) {
    int n = SZ(a), id = 0;
    for (int i = 0; i < n; i++, id++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz[id]++;
            srcId[j] = id;
            j++;
        }
        j--;
        low.pb(i);
        up.pb(j);
        i = j;
    }
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, low, up, srcId(n);
    for (int& x : a)
        cin >> x;
    assign(a, sz, low, up, srcId);
    MaxSegmentTree tree(sz);
    int ans = 0;
    int id;
    while ((id = tree.get()) != -1) {
        ans++;
        int l = low[id];
        int r = up[id];
        tree.modify(id);
        if (!l || r == n - 1)
            continue;
        int x = l - 1;
        int y = r + 1;
        if (a[x] == a[y]) {
            int u = srcId[x];
            int v = srcId[y];
            tree.modify(u);
            tree.modify(v);
            sz[v] = 0;
            sz[u] += sz[v];
            tree.modify(u, sz[u]);
            up[u] = up[v];
        }
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

pii combine(pii a, pii b) {
    if (a.first == b.first)
        return (a.second < b.second ? a : b);
    return (a.first > b.first ? a : b);
}

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        (pos < m) ? modify(pos, value, u + u + 1, l, m) : modify(pos, value, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

int assign(vector<int>& a, vector<int>& sz, vector<int>& sign) {
    int n = SZ(a);
    for (int i = 0; i < n; i++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz.back()++;
            j++;
        }
        sign.pb(a[i]);
        j--;
        i = j;
    }
    return SZ(sign);
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, sign;
    for (int& x : a)
        cin >> x;
    int lastId = assign(a, sz, sign);
    MaxSegmentTree tree(sz);
    set<int> stock;
    for (int id = 0; id < lastId; id++)
        stock.insert(id);
    int ans = 0;
    while (!stock.empty()) {
        int id = tree.get();
        assert(id != -1);
        // cout << "id: " << id;
        ans++;
        stock.erase(id);
        tree.modify(id);
        auto low = stock.lower_bound(id);
        auto up = stock.upper_bound(id);
        if (low == stock.begin() || up == stock.end()) {
            // cout << ", continued\n";
            continue;
        }
        low--;
        int u = *low;
        int v = *up;
        // cout << ", u: " << u << ", v: " << v << ", sign[u]: " << sign[u] << ", sign[v]: " << sign[v];
        if (sign[u] == sign[v]) {
            // cout << ", united";
            tree.modify(u);
            tree.modify(v);
            sz[u] += sz[v];
            sz[v] = 0;
            stock.erase(v);
            tree.modify(u, sz[u]);
        }
        // cout << '\n';
    }
    assert(tree.get() == -1);
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

pii combine(pii a, pii b) {
    if (a.first == b.first)
        return (a.second < b.second ? a : b);
    return (a.first > b.first ? a : b);
}

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        (pos < m) ? modify(pos, value, u + u + 1, l, m) : modify(pos, value, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

int assign(vector<int>& a, vector<int>& sz, vector<int>& sign) {
    int n = SZ(a);
    for (int i = 0; i < n; i++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz.back()++;
            j++;
        }
        sign.pb(a[i]);
        j--;
        i = j;
    }
    return SZ(sign);
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, sign;
    for (int& x : a)
        cin >> x;
    int lastId = assign(a, sz, sign);
    MaxSegmentTree tree(sz);
    set<int> stock;
    for (int id = 0; id < lastId; id++)
        stock.insert(id);
    int ans = 0;
    while (!stock.empty()) {
        int id = tree.get();
        assert(id != -1);
        // cout << "id: " << id;
        ans++;
        stock.erase(id);
        tree.modify(id);
        auto low = stock.lower_bound(id);
        auto up = stock.upper_bound(id);
        if (low == stock.begin() || up == stock.end()) {
            // cout << ", continued\n";
            continue;
        }
        low--;
        int u = *low;
        int v = *up;
        // cout << ", u: " << u << ", v: " << v << ", sign[u]: " << sign[u] << ", sign[v]: " << sign[v];
        if (sign[u] == sign[v]) {
            // cout << ", united";
            tree.modify(u);
            tree.modify(v);
            sz[u] += sz[v];
            sz[v] = 0;
            stock.erase(v);
            tree.modify(u, sz[u]);
        }
        // cout << '\n';
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

pii combine(pii a, pii b) {
    return (a.first != b.first ? (a.first > b.first ? a : b) : (a.second < b.second ? a : b));
}

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        (pos < m) ? modify(pos, value, u + u + 1, l, m) : modify(pos, value, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

int assign(vector<int>& a, vector<int>& sz, vector<int>& sign) {
    int n = SZ(a);
    for (int i = 0; i < n; i++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz.back()++;
            j++;
        }
        sign.pb(a[i]);
        j--;
        i = j;
    }
    return SZ(sign);
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, sign;
    for (int& x : a)
        cin >> x;
    int lastId = assign(a, sz, sign);
    MaxSegmentTree tree(sz);
    set<int> stock;
    for (int id = 0; id < lastId; id++)
        stock.insert(id);
    int ans = 0;
    while (!stock.empty()) {
        int id = tree.get();
        assert(id != -1);
        // cout << "id: " << id;
        ans++;
        stock.erase(id);
        tree.modify(id);
        auto low = stock.lower_bound(id);
        auto up = stock.upper_bound(id);
        if (low == stock.begin() || up == stock.end()) {
            // cout << ", continued\n";
            continue;
        }
        low--;
        int u = *low;
        int v = *up;
        // cout << ", u: " << u << ", v: " << v << ", sign[u]: " << sign[u] << ", sign[v]: " << sign[v];
        if (sign[u] == sign[v]) {
            // cout << ", united";
            tree.modify(u);
            tree.modify(v);
            sz[u] += sz[v];
            sz[v] = 0;
            stock.erase(v);
            tree.modify(u, sz[u]);
        }
        // cout << '\n';
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = max(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        (pos < m) ? modify(pos, value, u + u + 1, l, m) : modify(pos, value, u + u + 2, m, r);
        mx[u] = max(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

void assign(vector<int>& a, vector<int>& sz, vector<int>& low, vector<int>& up, vector<int>& srcId) {
    int n = SZ(a), id = 0;
    for (int i = 0; i < n; i++, id++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz[id]++;
            srcId[j] = id;
            j++;
        }
        j--;
        low.pb(i);
        up.pb(j);
        i = j;
    }
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, low, up, srcId(n);
    for (int& x : a)
        cin >> x;
    assign(a, sz, low, up, srcId);
    MaxSegmentTree tree(sz);
    int ans = 0;
    int id;
    while ((id = tree.get()) != -1) {
        ans++;
        int l = low[id];
        int r = up[id];
        tree.modify(id);
        if (!l || r == n - 1)
            continue;
        int x = l - 1;
        int y = r + 1;
        if (a[x] == a[y]) {
            int u = srcId[x];
            int v = srcId[y];
            tree.modify(u);
            tree.modify(v);
            sz[u] += sz[v];
            tree.modify(u, sz[u]);
            up[u] = up[v];
        }
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

pii combine(pii a, pii b) {
    return (a.first != b.first ? (a.first > b.first ? a : b) : (a.second < b.second ? a : b));
}

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        (pos < m) ? modify(pos, value, u + u + 1, l, m) : modify(pos, value, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

void assign(vector<int>& a, vector<int>& sz, vector<int>& low, vector<int>& up, vector<int>& srcId) {
    int n = SZ(a), id = 0;
    for (int i = 0; i < n; i++, id++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz[id]++;
            srcId[j] = id;
            j++;
        }
        j--;
        low.pb(i);
        up.pb(j);
        i = j;
    }
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, low, up, srcId(n);
    for (int& x : a)
        cin >> x;
    assign(a, sz, low, up, srcId);
    MaxSegmentTree tree(sz);
    int ans = 0;
    int id;
    while ((id = tree.get()) != -1) {
        ans++;
        int l = low[id];
        int r = up[id];
        tree.modify(id);
        if (!l || r == n - 1)
            continue;
        int x = l - 1;
        int y = r + 1;
        if (a[x] == a[y]) {
            int u = srcId[x];
            int v = srcId[y];
            tree.modify(u);
            tree.modify(v);
            sz[u] += sz[v];
            tree.modify(u, sz[u]);
            up[u] = up[v];
        }
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back
#define fi first
#define se second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

struct cmp {
    bool operator()(const pii& lhs, const pii& rhs) {
        return (lhs.fi != rhs.fi ? lhs.fi > rhs.fi : lhs.se < rhs.se);
    }
};

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int& x : a)
        cin >> x;
    vector<int> dsu(n);
    vector<int> sz(n);
    vector<int> low(n);
    vector<int> up(n);
    set<pii, cmp> s;
    for (int u = 0; u < n; u++) {
        s.insert({sz[u] = 1, dsu[u] = u});
        low[u] = up[u] = u;
    }
    function<int(int)> get = [&](int u) {
        return (dsu[u] == u ? u : dsu[u] = get(dsu[u]));
    };

    vector<bool> was(n);
    function<void(int, int)> unite = [&](int x, int y) {
        x = get(x);
        y = get(y);

        if (x == y)
            return;
        if (sz[x] > sz[y])
            swap(x, y);
        low[x] = min(low[x], low[y]);
        up[x] = max(up[x], up[y]);
        s.erase({sz[y], y});
        s.erase({sz[x], x});
        s.insert({sz[x] += sz[y], x});
        dsu[y] = x;
        was[y] = true;
    };
    for (int u = 0; u < n - 1; u++)
        if (a[u] == a[u + 1])
            unite(u, u + 1);
    int ans = 0;
    while (!s.empty()) {
        int x = get(s.begin()->se);
        s.erase(s.begin());
        ans++;
        was[x] = true;
        int l = low[x];
        int r = up[x];
        if (!l || r == n - 1)
            continue;
        int u = get(l - 1);
        int v = get(r + 1);
        if (a[u] == a[v] && !was[u] && !was[v])
            unite(u, v);
    }
    cout << ans;
    return false;
}


#include <bits/stdc++.h>

#define FILE_NAME "899E"
#define SZ(x) ((int) x.size())
#define pb push_back
#define ppb pop_back

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

pii combine(pii a, pii b) {
    if (a.first == b.first)
        return (a.second < b.second ? a : b);
    return (a.first > b.first ? a : b);
}

struct MaxSegmentTree {
    int n;
    vector<pii> mx;

    MaxSegmentTree(vector<int>& a) : n(SZ(a)) {
        mx.resize(n << 2);
        build(a, 0, 0, n);
    }

    void build(vector<int>& a, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {a[l], l};
            return;
        }
        int m = (l + r) >> 1;
        build(a, u + u + 1, l, m);
        build(a, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value, int u, int l, int r) {
        if (r - l == 1) {
            mx[u] = {value, l};
            return;
        }
        int m = (l + r) >> 1;
        (pos < m) ? modify(pos, value, u + u + 1, l, m) : modify(pos, value, u + u + 2, m, r);
        mx[u] = combine(mx[u + u + 1], mx[u + u + 2]);
    }

    void modify(int pos, int value = 0) {
        modify(pos, value, 0, 0, n);
    }

    pii get(int u, int l, int r) {
        if (r - l == 1)
            return mx[u];
        int m = (l + r) >> 1;
        return (mx[u + u + 1] >= mx[u + u + 2] ? get(u + u + 1, l, m) : get(u + u + 2, m, r));
    }

    int get() {
        auto res = get(0, 0, n);
        return (res.first ? res.second : -1);
    }
};

int assign(vector<int>& a, vector<int>& sz, vector<int>& sign) {
    int n = SZ(a);
    for (int i = 0; i < n; i++) {
        int j = i;
        sz.pb(0);
        while (j < n && a[j] == a[i]) {
            sz.back()++;
            j++;
        }
        sign.pb(a[i]);
        j--;
        i = j;
    }
    return SZ(sign);
}

signed main() {
#ifdef LOCAL
    freopen(FILE_NAME".in", "r", stdin);
    freopen(FILE_NAME".out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    vector<int> a(n), sz, sign;
    for (int& x : a)
        cin >> x;
    int lastId = assign(a, sz, sign);
    MaxSegmentTree tree(sz);
    set<int> stock;
    for (int id = 0; id < lastId; id++)
        stock.insert(id);
    int ans = 0;
    while (!stock.empty()) {
        int id = tree.get();
        assert(id != -1);
        // cout << "id: " << id;
        ans++;
        stock.erase(id);
        tree.modify(id);
        sz[id] = 0;
        auto low = stock.lower_bound(id);
        auto up = stock.upper_bound(id);
        if (low == stock.begin() || up == stock.end()) {
            // cout << ", continued\n";
            continue;
        }
        low--;
        int u = *low;
        int v = *up;
        // cout << ", u: " << u << ", v: " << v << ", sign[u]: " << sign[u] << ", sign[v]: " << sign[v];
        if (sign[u] == sign[v]) {
            // cout << ", united";
            tree.modify(u);
            tree.modify(v);
            sz[u] += sz[v];
            sz[v] = 0;
            stock.erase(v);
            tree.modify(u, sz[u]);
        }
        // cout << '\n';
    }
    assert(tree.get() == -1);
    cout << ans;
    return false;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[200005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;cnt=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            d[l]={{cnt,p},{l,r}};
            d[r]={{cnt,p},{l,r}};
            q.insert({-1*cnt,{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++,cnt++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*cnt,{l,r}});
    d[l]={{cnt,p},{l,r}};
    d[r]={{cnt,p},{l,r}};
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        if (l==0 || r==n+1)break;
        ans++;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
        else
        {
            if(r<n)
            {
                q.erase({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
                d[r+1].se.fi=d[l].se.fi;
                q.insert({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
            }
            d[r]={{0,0},{0,0}};
            d[l]=d[r+1];
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[200005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;cnt=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            d[l]={{cnt,p},{l,r}};
            d[r]={{cnt,p},{l,r}};
            q.insert({-1*cnt,{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++,cnt++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*cnt,{l,r}});
    d[l]={{cnt,p},{l,r}};
    d[r]={{cnt,p},{l,r}};
    cout<<q.size()<<endl;
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        if (l==0 || r==n+1)break;
        ans++;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
        else
        {
            if(r<n)
            {
                q.erase({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
                d[r+1].se.fi=d[l].se.fi;
                q.insert({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
            }
            d[l]=d[r+1];
            d[r]=d[r+1];
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[200005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;cnt=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            for (j=l;j<=r;j++)
            d[j]={{cnt,p},{l,r}};
            q.insert({-1*cnt,{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++,cnt++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*cnt,{l,r}});
    for (j=l;j<=r;j++)
        d[j]={{cnt,p},{l,r}};
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        ans++;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[300005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            d[l]={{(r-l+1),p},{l,r}};
            d[r]={{(r-l+1),p},{l,r}};
            q.insert({-1*(r-l+1),{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*(r-l+1),{l,r}});
    d[l]={{(r-l+1),p},{l,r}};
    d[r]={{(r-l+1),p},{l,r}};
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        ill c=q.begin()->fi;
        ans++;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            d[l-1].se.se=d[r+1].se.se;
            d[r+1].se.fi=d[l-1].se.fi;
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
        else
        {
            if(r<n)
            {
                ill z=d[r+1].se.se;
                q.erase({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
                d[z]={{d[r+1].fi.fi,d[r+1].fi.se},{l,z}};
                d[r]=d[z];
                d[l]=d[z];
                q.insert({d[z].fi.fi*-1,{d[z].se.fi,d[z].se.se}});
            }
            if(r==n && l>1)
            {
                ill z=d[l-1].se.fi;
                q.erase({d[l-1].fi.fi*-1,{d[l-1].se.fi,d[l-1].se.se}});
                d[z]={{d[l-1].fi.fi,d[l-1].fi.se},{z,r}};
                d[r]=d[z];
                d[l]=d[z];
                q.insert({d[z].fi.fi*-1,{d[z].se.fi,d[z].se.se}});
            }
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[300005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            d[l]={{(r-l+1),p},{l,r}};
            d[r]={{(r-l+1),p},{l,r}};
            q.insert({-1*(r-l+1),{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*(r-l+1),{l,r}});
    d[l]={{(r-l+1),p},{l,r}};
    d[r]={{(r-l+1),p},{l,r}};
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        ill c=q.begin()->fi;
        ans++;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            d[l-1].se.se=d[r+1].se.se;
            d[r+1].se.fi=d[l-1].se.fi;
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
        else
        {
            if(r<n)
            {
                ill z=d[r+1].se.se;
                q.erase({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
                d[z]={{d[r+1].fi.fi,d[r+1].fi.se},{l,z}};
                q.insert({d[z].fi.fi*-1,{d[z].se.fi,d[z].se.se}});
            }
            else if(l>1)
            {
                ill z=d[l-1].se.fi;
                q.erase({d[l-1].fi.fi*-1,{d[l-1].se.fi,d[l-1].se.se}});
                d[z]={{d[l-1].fi.fi,d[l-1].fi.se},{z,r}};
                q.insert({d[z].fi.fi*-1,{d[z].se.fi,d[z].se.se}});
            }
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[200005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;cnt=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            d[l]={{cnt,p},{l,r}};
            d[r]={{cnt,p},{l,r}};
            q.insert({-1*cnt,{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++,cnt++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*cnt,{l,r}});
    d[l]={{cnt,p},{l,r}};
    d[r]={{cnt,p},{l,r}};
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        if (l==0 || r==n+1)break;
        ans++;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
        else
        {
            if(r<n)
            {
                q.erase({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
                d[r+1].se.fi=d[l].se.fi;
                q.insert({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
            }
            d[l]=d[r+1];
            d[r]=d[r+1];
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[300005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            d[l]={{(r-l+1),p},{l,r}};
            d[r]={{(r-l+1),p},{l,r}};
            q.insert({-1*(r-l+1),{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*(r-l+1),{l,r}});
    d[l]={{(r-l+1),p},{l,r}};
    d[r]={{(r-l+1),p},{l,r}};
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        ill c=q.begin()->fi;
        ans++;
        if(l==1 && r==n)break;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            d[l-1].se.se=d[r+1].se.se;
            d[r+1].se.fi=d[l-1].se.fi;
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
        else
        {
            if(r<n)
            {
                ill z=d[r+1].se.se;
                q.erase({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
                d[z]={{d[r+1].fi.fi,d[r+1].fi.se},{l,z}};
                q.insert({d[z].fi.fi*-1,{d[z].se.fi,d[z].se.se}});
            }
            if(l>1)
            {
                ill z=d[l-1].se.fi;
                q.erase({d[l-1].fi.fi*-1,{d[l-1].se.fi,d[l-1].se.se}});
                d[z]={{d[l-1].fi.fi,d[l-1].fi.se},{z,r}};
                q.insert({d[z].fi.fi*-1,{d[z].se.fi,d[z].se.se}});
            }
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[300005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            d[l]={{(r-l+1),p},{l,r}};
            d[r]={{(r-l+1),p},{l,r}};
            q.insert({-1*(r-l+1),{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*(r-l+1),{l,r}});
    d[l]={{(r-l+1),p},{l,r}};
    d[r]={{(r-l+1),p},{l,r}};
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        ill c=q.begin()->fi;
        ans++;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            d[l-1].se.se=d[r+1].se.se;
            d[r+1].se.fi=d[l-1].se.fi;
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
        else
        {
            if(r<n)
            {
                ill z=d[r+1].se.se;
                q.erase({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
                d[z]={{d[r+1].fi.fi,d[r+1].fi.se},{l,z}};
                d[d[r+1].se.fi]=d[z];
                d[r]=d[z];
                d[l]=d[z];
                q.insert({d[z].fi.fi*-1,{d[z].se.fi,d[z].se.se}});
            }
            if(l>1)
            {
                ill z=d[l-1].se.fi;
                q.erase({d[l-1].fi.fi*-1,{d[l-1].se.fi,d[l-1].se.se}});
                d[z]={{d[l-1].fi.fi,d[l-1].fi.se},{z,r}};
                d[r]=d[z];
                d[d[l-1].se.se]=d[z];
                d[l]=d[z];
                q.insert({d[z].fi.fi*-1,{d[z].se.fi,d[z].se.se}});
            }
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
#define ill int long long
#define fi first
#define se second
using namespace std ;
ill n,p,l,r,cnt,i,ans,j;
set< pair < ill, pair <ill,ill> > > q;
pair < pair <ill,ill> , pair <ill,ill> > d[200005];
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
    //freopen("monster.in" , "r" , stdin);
    //freopen("monster.out" , "w" , stdout);
    cin>>n>>p;
    l=1,r=1;cnt=1;
    for (i=2;i<=n;i++)
    {
        ill x;
        cin>>x;
        if (p!=x)
        {
            d[l]={{cnt,p},{l,r}};
            d[r]={{cnt,p},{l,r}};
            q.insert({-1*cnt,{l,r}});
            cnt=1;
            l=i;
            r=i;
        }
        else
            r++,cnt++;
        p=x;
    }
    d[0]={{0,-1e9},{0,0}};
    d[n+1]={{0,1e9},{n+1,n+1}};
    q.insert({-1*cnt,{l,r}});
    d[l]={{cnt,p},{l,r}};
    d[r]={{cnt,p},{l,r}};
    while (!q.empty())
    {
        ill l=q.begin()->se.fi;
        ill r=q.begin()->se.se;
        if (l==0 || r==n+1)break;
        ans++;
        q.erase(q.begin());
        if (d[l-1].fi.se==d[r+1].fi.se)
        {
            q.erase({-1*d[l-1].fi.fi,{d[l-1].se.fi,d[l-1].se.se}});
            q.erase({-1*d[r+1].fi.fi,{d[r+1].se.fi,d[r+1].se.se}});
            q.insert({-1*(d[l-1].fi.fi+d[r+1].fi.fi),{d[l-1].se.fi,d[r+1].se.se}});
        }
        else
        {
            if(r<n)
            {
                q.erase({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
                d[r+1].se.fi=d[l].se.fi;
                q.insert({d[r+1].fi.fi*-1,{d[r+1].se.fi,d[r+1].se.se}});
            }
            d[l]=d[r+1];
            d[r]={{0,0},{0,0}};
        }
    }
    cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;

int N;
vector<int> arr;

struct node {
    int mx, val, optl, optr, lmx, lval, loptr, rmx, rval, roptl, len;
};

node mrg(node &a, node &b) {
    if(a.mx == -1) return b;
    if(b.mx == -1) return a;
    node ret;

    if(a.mx >= b.mx) ret.mx = a.mx, ret.val = a.val, ret.optl = a.optl, ret.optr = a.optr;
    else ret.mx = b.mx, ret.val = b.val, ret.optl = b.optl, ret.optr = b.optr;
    if(a.rval == b.lval && (ret.mx < a.rmx + b.lmx || (ret.mx == a.rmx + b.lmx && ret.optl > a.roptl))) {
        ret.mx = a.rmx + b.lmx, ret.val = a.rval, ret.optl = a.roptl, ret.optr = b.loptr;
    }

    if(a.len == a.lmx && a.lval == b.lval) ret.lmx = a.lmx + b.lmx, ret.lval = a.lval, ret.loptr = b.loptr;
    else ret.lmx = a.lmx, ret.lval = a.lval, ret.loptr = a.loptr;
    if(b.len == b.rmx && a.rval == b.rval) ret.rmx = a.rmx + b.rmx, ret.rval = b.rval, ret.roptl = a.roptl;
    else ret.rmx = b.rmx, ret.rval = b.rval, ret.roptl = b.roptl;

    ret.len = a.len + b.len;

    return ret;
}

struct BIT {
    vector<node> tree;
    vector<int> lazy;
    void init() {
        tree = vector<node>(4*N);
        lazy = vector<int>(4*N, 0);
        build(0, N - 1, 1);
    }
    void build(int l, int r, int n) {
        if(l == r) {
            tree[n] = { 1, arr[l], l, l, 1, arr[l], l, 1, arr[l], l, 1 };
            return;
        }
        int m = (l + r)>>1;
        build(l, m, 2*n);
        build(m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    void prop(int l, int r, int n) {
        if(l != r && lazy[n]) {
            tree[2*n] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
            lazy[2*n] = 1;
            tree[2*n + 1] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
            lazy[2*n + 1] = 1;
            lazy[n] = 0;
        }
    }
    void upd(int a, int b, int l, int r, int n) {
        if(b < l || r < a) return;
        if(a <= l && r <= b) {
            tree[n] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
            lazy[n] = 1;
            return;
        }
        prop(l, r, n);
        int m = (l + r)>>1;
        upd(a, b, l, m, 2*n);
        upd(a, b, m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    node quer(int a, int b, int l, int r, int n) {
        if(b < l || r < a) return {-1, -1, -1, -1, -1, -1, -1, -1};
        if(a <= l && r <= b) return tree[n];
        prop(l, r, n);
        int m = (l + r)>>1;
        node L = quer(a, b, l, m, 2*n);
        node R = quer(a, b, m + 1, r, 2*n + 1);
        return mrg(L, R);
    }
} bit;

int main() {
    scanf("%d", &N);

    arr.resize(N);
    for(int i = 0; i < N; i++) {
        scanf("%d", &arr[i]);
    }

    bit.init();

    int cnt = 0;
    while(1) {
        node t = bit.quer(0, N - 1, 0, N - 1, 1);
        if(t.mx == -1) break;

        bit.upd(t.optl, t.optr, 0, N - 1, 1);
        cnt++;
    }

    printf("%d", cnt);
}


#include<bits/stdc++.h>
using namespace std;

int N;
vector<int> arr;

struct node {
    int mx, val, optl, optr, lmx, lval, rmx, rval, l, r;
};

node mrg(node &a, node &b) {
    if(a.mx == -1) return b;
    if(b.mx == -1) return a;
    node ret;

    if(a.mx >= b.mx) ret.mx = a.mx, ret.val = a.val, ret.optl = a.optl, ret.optr = a.optr;
    else ret.mx = b.mx, ret.val = b.val, ret.optl = b.optl, ret.optr = b.optr;
    if(a.rval == b.lval && (ret.mx < a.rmx + b.lmx || (ret.mx == a.rmx + b.lmx && ret.optl > a.r - a.rmx + 1))) {
        ret.mx = a.rmx + b.lmx, ret.val = a.rval, ret.optl = a.r - a.rmx + 1, ret.optr = b.l + b.lmx - 1;
    }

    if(a.r - a.l + 1 == a.lmx && a.lval == b.lval) ret.lmx = a.lmx + b.lmx, ret.lval = a.lval;
    else ret.lmx = a.lmx, ret.lval = a.lval;
    if(b.r - b.l + 1 == b.rmx && a.rval == b.rval) ret.rmx = a.rmx + b.rmx, ret.rval = b.rval;
    else ret.rmx = b.rmx, ret.rval = b.rval;

    ret.l = a.l;
    ret.r = b.r;

    return ret;
}

struct BIT {
    vector<node> tree;
    vector<int> lazy;
    void init() {
        tree = vector<node>(4*N);
        lazy = vector<int>(4*N, 0);
        build(0, N - 1, 1);
    }
    void build(int l, int r, int n) {
        if(l == r) {
            tree[n] = { 1, arr[l], l, l, 1, arr[l], 1, arr[l], l, l };
            return;
        }
        int m = (l + r)>>1;
        build(l, m, 2*n);
        build(m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    void prop(int l, int r, int n) {
        if(l != r && lazy[n]) {
            tree[2*n] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
            lazy[2*n] = 1;
            tree[2*n + 1] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
            lazy[2*n + 1] = 1;
            lazy[n] = 0;
        }
    }
    void upd(int a, int b, int l, int r, int n) {
        if(b < l || r < a) return;
        if(a <= l && r <= b) {
            tree[n] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
            lazy[n] = 1;
            return;
        }
        prop(l, r, n);
        int m = (l + r)>>1;
        upd(a, b, l, m, 2*n);
        upd(a, b, m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    node quer(int a, int b, int l, int r, int n) {
        if(b < l || r < a) return {-1, -1, -1, -1, -1, -1, -1};
        if(a <= l && r <= b) return tree[n];
        prop(l, r, n);
        int m = (l + r)>>1;
        node L = quer(a, b, l, m, 2*n);
        node R = quer(a, b, m + 1, r, 2*n + 1);
        return mrg(L, R);
    }
} bit;

int main() {
    scanf("%d", &N);

    arr.resize(N);
    for(int i = 0; i < N; i++) {
        scanf("%d", &arr[i]);
    }

    bit.init();

    int cnt = 0;
    while(1) {
        node t = bit.quer(0, N - 1, 0, N - 1, 1);
        if(t.mx == -1) break;

        bit.upd(t.optl, t.optr, 0, N - 1, 1);
        cnt++;
    }

    printf("%d", cnt);
}


#include<bits/stdc++.h>
using namespace std;

int N;
vector<int> arr, pre, nxt, Len, le, ri;

struct Info {
    int l, r, len;
    bool operator <(const Info &i) const {
        if(len != i.len) return len > i.len;
        else return l < i.l;
    }
};
set<Info> st;

int main() {
    scanf("%d", &N);

    arr.resize(N);
    for(int i = 0; i < N; i++) {
        scanf("%d", &arr[i]);
    }

    pre.resize(N);
    nxt.resize(N);
    Len.resize(N);
    le.resize(N);
    ri.resize(N);
    for(int i = 0; i < N; i++) {
        if(i && arr[i - 1] == arr[i]) {
            pre[i] = pre[i - 1];
        }
        else pre[i] = i;
    }
    for(int i = N - 1; i >= 0; i--) {
        if(i != N - 1 && arr[i + 1] == arr[i]) {
            nxt[i] = nxt[i + 1];
        }
        else nxt[i] = i;
    }
    for(int i = 0; i < N; i++) {
        le[i] = i - 1;
        ri[i] = i + 1;
    }

    int pos = 0;
    while(pos < N) {
        st.insert({pos, nxt[pos], nxt[pos] - pos + 1});
        Len[pos] = nxt[pos] - pos + 1;
        Len[nxt[pos]] = nxt[pos] - pos + 1;
        pos = nxt[pos] + 1;
    }

    int cnt = 0;
    while(st.size()) {
        Info t = *st.begin(); st.erase(st.begin());

        if(le[t.l] != -1) ri[ le[t.l] ] = ri[t.r];
        if(ri[t.r] != N) le[ ri[t.r] ] = le[t.l];

        if(le[t.l] != -1 && ri[t.r] != N && arr[ le[t.l] ] == arr[ ri[t.r] ]) {
            st.erase(st.find({pre[ le[t.l] ], le[t.l], Len[ le[t.l] ]}));
            st.erase(st.find({ri[t.r], nxt[ ri[t.r] ], Len[ ri[t.r] ]}));
            st.insert({ pre[ le[t.l] ], nxt[ ri[t.r] ], Len[ le[t.l] ] + Len[ ri[t.r] ] });
            nxt[ pre[ le[t.l] ] ] = nxt[ ri[t.r] ];
            pre[ nxt[ ri[t.r] ] ] = pre[ le[t.l] ];
            int tmp = Len[ le[t.l] ] + Len[ ri[t.r] ];
            Len[ pre[ le[t.l] ] ] = tmp;
            Len[ nxt[ ri[t.r] ] ] = tmp;
        }

        cnt++;
    }
    printf("%d", cnt);
}


#include<bits/stdc++.h>
using namespace std;

int N;
vector<int> arr, pre, nxt, Len;

struct Info {
    int l, r, len;
    bool operator <(const Info &i) const {
        if(len != i.len) return len > i.len;
        else return l < i.l;
    }
};
set<Info> st;

int main() {
    scanf("%d", &N);

    arr.resize(N);
    for(int i = 0; i < N; i++) {
        scanf("%d", &arr[i]);
    }

    pre.resize(N);
    nxt.resize(N);
    Len.resize(N);
    for(int i = 0; i < N; i++) {
        if(i && arr[i - 1] == arr[i]) {
            pre[i] = pre[i - 1];
        }
        else pre[i] = i;
    }
    for(int i = N - 1; i >= 0; i--) {
        if(i != N - 1 && arr[i + 1] == arr[i]) {
            nxt[i] = nxt[i + 1];
        }
        else nxt[i] = i;
    }

    int pos = 0;
    while(pos < N) {
        st.insert({pos, nxt[pos], nxt[pos] - pos + 1});
        Len[pos] = nxt[pos] - pos + 1;
        Len[nxt[pos]] = nxt[pos] - pos + 1;
        pos = nxt[pos] + 1;
    }

    int cnt = 0;
    while(st.size()) {
        Info t = *st.begin(); st.erase(st.begin());

        if(t.l && t.r < N - 1 && arr[t.l - 1] == arr[t.r + 1] && st.find({ pre[t.l - 1], t.l - 1, Len[t.l - 1] }) != st.end() && st.find({ t.r + 1, nxt[t.r + 1], Len[t.r + 1] }) != st.end()) {
            st.erase(st.find({ pre[t.l - 1], t.l - 1, Len[t.l - 1] }));
            st.erase(st.find({ t.r + 1, nxt[t.r + 1], Len[t.r + 1] }));
            nxt[t.l - 1] = nxt[t.r + 1];
            pre[t.r + 1] = pre[t.l - 1];
            st.insert({ pre[t.l - 1], nxt[t.r + 1], Len[t.l - 1] + Len[t.r + 1] });
            int tmp = Len[t.l - 1] + Len[t.r + 1];
            Len[ pre[t.l - 1] ] = tmp;
            Len[ nxt[t.r + 1] ] = tmp;
        }
        cnt++;
    }
    printf("%d", cnt);
}


#include<bits/stdc++.h>
using namespace std;

int N;
vector<int> arr, pre, nxt, Len;

struct Info {
    int l, r, len;
    bool operator <(const Info &i) const {
        if(len != i.len) return len > i.len;
        else return l < i.l;
    }
};
set<Info> st;

int main() {
    scanf("%d", &N);

    arr.resize(N);
    for(int i = 0; i < N; i++) {
        scanf("%d", &arr[i]);
    }

    pre.resize(N);
    nxt.resize(N);
    Len.resize(N);
    for(int i = 0; i < N; i++) {
        if(i && arr[i - 1] == arr[i]) {
            pre[i] = pre[i - 1];
        }
        else pre[i] = i;
    }
    for(int i = N - 1; i >= 0; i--) {
        if(i != N - 1 && arr[i + 1] == arr[i]) {
            nxt[i] = nxt[i + 1];
        }
        else nxt[i] = i;
    }

    int pos = 0;
    while(pos < N) {
        st.insert({pos, nxt[pos], nxt[pos] - pos + 1});
        Len[pos] = nxt[pos] - pos + 1;
        Len[nxt[pos]] = nxt[pos] - pos + 1;
        pos = nxt[pos] + 1;
    }

    int cnt = 0;
    while(st.size()) {
        Info t = *st.begin(); st.erase(st.begin());

        if(t.l && t.r < N - 1 && arr[t.l - 1] == arr[t.r + 1] && st.find({ pre[t.l - 1], t.l - 1, Len[t.l - 1] }) != st.end() && st.find({ t.r + 1, nxt[t.r + 1], Len[t.r + 1] }) != st.end()) {
            st.erase(st.find({ pre[t.l - 1], t.l - 1, Len[t.l - 1] }));
            st.erase(st.find({ t.r + 1, nxt[t.r + 1], Len[t.r + 1] }));
            nxt[t.l - 1] = nxt[t.r + 1];
            pre[t.r + 1] = pre[t.l - 1];
            st.insert({ pre[t.l - 1], nxt[t.r + 1], Len[t.l - 1] + Len[t.r + 1] });
            int tmp = Len[t.l - 1] + Len[t.r + 1];
            Len[t.l - 1] = tmp;
            Len[t.r + 1] = tmp;
        }
        cnt++;
    }
    printf("%d", cnt);
}


#include<bits/stdc++.h>
using namespace std;

int N;
vector<int> arr, pre, nxt, Len, le, ri;

struct Info {
    int l, r, len;
    bool operator <(const Info &i) const {
        if(len != i.len) return len > i.len;
        else return l < i.l;
    }
};
set<Info> st;

int main() {
    scanf("%d", &N);

    arr.resize(N);
    for(int i = 0; i < N; i++) {
        scanf("%d", &arr[i]);
    }

    pre.resize(N);
    nxt.resize(N);
    Len.resize(N);
    le.resize(N);
    ri.resize(N);
    for(int i = 0; i < N; i++) {
        if(i && arr[i - 1] == arr[i]) {
            pre[i] = pre[i - 1];
        }
        else pre[i] = i;
    }
    for(int i = N - 1; i >= 0; i--) {
        if(i != N - 1 && arr[i + 1] == arr[i]) {
            nxt[i] = nxt[i + 1];
        }
        else nxt[i] = i;
    }
    for(int i = 0; i < N; i++) {
        le[i] = i - 1;
        ri[i] = i + 1;
    }

    int pos = 0;
    while(pos < N) {
        st.insert({pos, nxt[pos], nxt[pos] - pos + 1});
        Len[pos] = nxt[pos] - pos + 1;
        Len[nxt[pos]] = nxt[pos] - pos + 1;
        pos = nxt[pos] + 1;
    }

    int cnt = 0;
    while(st.size()) {
        Info t = *st.begin(); st.erase(st.begin());

        if(le[t.l] != -1) ri[ le[t.l] ] = ri[t.r];
        if(ri[t.r] != N) le[ ri[t.r] ] = le[t.l];

        if(le[t.l] != -1 && ri[t.r] != N && arr[ le[t.l] ] == arr[ ri[t.r] ]) {
            st.erase(st.find({pre[ le[t.l] ], le[t.l], Len[ le[t.l] ]}));
            st.erase(st.find({ri[t.r], nxt[ ri[t.r] ], Len[ ri[t.r] ]}));
            st.insert({ pre[ le[t.l] ], nxt[ ri[t.r] ], Len[ le[t.l] ] + Len[ ri[t.r] ] });
            nxt[ pre[ le[t.l] ] ] = nxt[ ri[t.r] ];
            pre[ nxt[ ri[t.r] ] ] = pre[ le[t.l] ];
            Len[ pre[ le[t.l] ] ] = Len[ le[t.l] ] + Len[ ri[t.r] ];
            Len[ nxt[ ri[t.r] ] ] = Len[ le[t.l] ] + Len[ ri[t.r] ];
        }

        cnt++;
    }
    printf("%d", cnt);
}


#include<bits/stdc++.h>
using namespace std;

int N;
vector<int> arr, pre, nxt;

struct Info {
    int l, r;
    bool operator <(const Info &i) const {
        if(r - l != i.r - i.l) return r - l > i.r - i.l;
        else return l < i.l;
    }
};
set<Info> st;

int main() {
    scanf("%d", &N);

    arr.resize(N);
    for(int i = 0; i < N; i++) {
        scanf("%d", &arr[i]);
    }

    pre.resize(N);
    nxt.resize(N);
    for(int i = 0; i < N; i++) {
        if(i && arr[i - 1] == arr[i]) {
            pre[i] = pre[i - 1];
        }
        else pre[i] = i;
    }
    for(int i = N - 1; i >= 0; i--) {
        if(i != N - 1 && arr[i + 1] == arr[i]) {
            nxt[i] = nxt[i + 1];
        }
        else nxt[i] = i;
    }

    int pos = 0;
    while(pos < N) {
        st.insert({pos, nxt[pos]});
        pos = nxt[pos] + 1;
    }

    int cnt = 0;
    while(st.size()) {
        Info t = *st.begin(); st.erase(st.begin());

        if(t.l && t.r < N - 1 && arr[t.l - 1] == arr[t.r + 1] && st.find({ pre[t.l - 1], t.l - 1 }) != st.end() && st.find({ t.r + 1, nxt[t.r + 1] }) != st.end()) {
            st.erase(st.find({ pre[t.l - 1], t.l - 1 }));
            st.erase(st.find({ t.r + 1, nxt[t.r + 1] }));
            nxt[t.l - 1] = nxt[t.r + 1];
            pre[t.r + 1] = pre[t.l - 1];
            st.insert({ pre[t.l - 1], nxt[t.r + 1] });
        }
        cnt++;
    }
    printf("%d", cnt);
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int size = 1e6 + 10;

int a[size],n;
/*l-r, type
*/struct segment
{
	int l,r,len,value;
};
struct classcomp
{
	bool operator() (const segment& lhs, const segment& rhs) const
	{
		if(lhs.len==rhs.len)
			return lhs.l> rhs.l;
		return lhs.len<rhs.len;
	}
};
int main()
{
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i=0;i<n;i++)
		cin >> a[i];

	vector<segment> v;
	v.push_back({0,0,1,a[0]});
	for(int i=1;i<n;i++)
	{
		if(a[i]==a[i-1])
		{
			v[v.size()-1].r=i;
			v[v.size()-1].len++;
		}
		else
			v.push_back({i,i,1,a[i]});
	}
	set<segment,classcomp> s;
	map<int,segment> left,right;
	for(auto i:v)
	{
		s.insert(i);
		left[i.l]=i;
		right[i.r]=i;
	}
	ll c=0;
	while(s.size())
	{
		/*for(auto i:s)
			cout << i.l << " " << i.r << " " << i.len << " " << i.value << endl;
		cout << endl;
		*/c++;
		segment temp=*s.rbegin();
		s.erase(temp);
		segment temp2=right[temp.l-1];
		segment temp3=left[temp.r+1];
		if(s.find(temp2) == s.end())
			continue;
		if(s.find(temp3) == s.end())
			continue;
		s.erase(temp2);
		if(temp2.value!=temp3.value)
		{
			temp2.r=temp3.l-1;
			s.insert(temp2);
			right[temp2.r]=temp2;
			continue;
		}
		s.erase(temp3);
		segment temp4={temp2.l,temp3.r,temp2.len+temp3.len,temp2.value};
		left[temp2.l]=temp4;
		right[temp3.r]=temp4;
		s.insert(temp4);
	}
	cout << c;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int size = 1e6 + 10;

int a[size],n;
struct segment
{
	int l,r,len,value;
};
struct classcomp
{
	bool operator() (const segment& lhs, const segment& rhs) const
	{
		if(lhs.len==rhs.len)
			return lhs.l> rhs.l;
		return lhs.len<rhs.len;
	}
};
int main()
{
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i=0;i<n;i++)
		cin >> a[i];

	vector<segment> v;
	v.push_back({0,0,1,a[0]});
	for(int i=1;i<n;i++)
	{
		if(a[i]==a[i-1])
		{
			v[v.size()-1].r=i;
			v[v.size()-1].len++;
		}
		else
			v.push_back({i,i,1,a[i]});
	}
	set<segment,classcomp> s;
	map<int,segment> left,right;
	for(auto i:v)
	{
		s.insert(i);
		left[i.l]=i;
		right[i.r]=i;
	}
	ll c=0;
	ll x;
	while(s.size())
	{
		c++;

		segment temp=*s.rbegin();
		if(s.size()<=20&&n==200000)
		{
			cout << endl << s.size() << endl;
			for(auto temp:s)
				cout << temp.l << " " << temp.r << " "<<  temp.len << " " <<temp.value << endl;
		}
		s.erase(temp);
		if(temp.l==0||temp.r==n-1)
			continue;
		segment temp2=right[temp.l-1];
		segment temp3=left[temp.r+1];
		if(s.find(temp2) == s.end())
			continue;
		if(s.find(temp3) == s.end())
			continue;
		s.erase(temp2);
		if(temp2.value!=temp3.value)
		{
			temp2.r=temp3.l-1;
			s.insert(temp2);
			right[temp2.r]=temp2;
			continue;
		}
		s.erase(temp3);
		segment temp4={temp2.l,temp3.r,temp2.len+temp3.len,temp2.value};
		left[temp2.l]=temp4;
		right[temp3.r]=temp4;
		s.insert(temp4);
	}
	cout << c;

}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int size = 1e6 + 10;

int a[size],n;
struct segment
{
	int l,r,len,value;
};
struct classcomp
{
	bool operator() (const segment& lhs, const segment& rhs) const
	{
		if(lhs.len==rhs.len)
			return lhs.l> rhs.l;
		return lhs.len<rhs.len;
	}
};
int main()
{
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i=0;i<n;i++)
		cin >> a[i];

	vector<segment> v;
	v.push_back({0,0,1,a[0]});
	for(int i=1;i<n;i++)
	{
		if(a[i]==a[i-1])
		{
			v[v.size()-1].r=i;
			v[v.size()-1].len++;
		}
		else
			v.push_back({i,i,1,a[i]});
	}
	set<segment,classcomp> s;
	map<int,segment> left,right;
	for(auto i:v)
	{
		s.insert(i);
		left[i.l]=i;
		right[i.r]=i;
	}
	ll c=0;
	ll x;
	while(s.size())
	{
		c++;

		segment temp=*s.rbegin();
		if(s.size()==1&&n==200000)
		{
			cout << temp.l << " " << temp.r << " "<<  temp.len << " " <<temp.value << endl;
		}
		s.erase(temp);
		if(temp.l==0||temp.r==n-1)
			continue;
		segment temp2=right[temp.l-1];
		segment temp3=left[temp.r+1];
		if(s.find(temp2) == s.end())
			continue;
		if(s.find(temp3) == s.end())
			continue;
		s.erase(temp2);
		if(temp2.value!=temp3.value)
		{
			temp2.r=temp3.l-1;
			s.insert(temp2);
			right[temp2.r]=temp2;
			continue;
		}
		s.erase(temp3);
		segment temp4={temp2.l,temp3.r,temp2.len+temp3.len,temp2.value};
		left[temp2.l]=temp4;
		right[temp3.r]=temp4;
		s.insert(temp4);
	}
	cout << c;

}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int size = 1e6 + 10;

int a[size],n;
/*l-r, type
*/struct segment
{
	int l,r,len,value;
};
struct classcomp {
  bool operator() (const segment& lhs, const segment& rhs) const
  {
  	if(lhs.len==rhs.len)
  		return lhs.l> rhs.l;
  	return lhs.len<rhs.len;
  }
};
int main()
{
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i=0;i<n;i++)
		cin >> a[i];

	vector<segment> v;
	v.push_back({0,0,1,a[0]});
	for(int i=1;i<n;i++)
	{
		if(a[i]==a[i-1])
		{
			v[v.size()-1].r=i;
			v[v.size()-1].len++;
		}
		else
			v.push_back({i,i,1,a[i]});
	}
	set<segment,classcomp> s;
	map<int,segment> left,right;
	for(auto i:v)
	{
		s.insert(i);
		left[i.l]=i;
		right[i.r]=i;
	}
	ll c=0;
	while(s.size())
	{
		c++;
		segment temp=*s.rbegin();
		s.erase(temp);
		if(temp.l==0||temp.r==n-1)
			continue;
		segment temp2=right[temp.l-1];
		segment temp3=left[temp.r+1];
		if(temp2.value!=temp3.value)
			continue;
		if(s.find(temp2) == s.end())
			continue;
		if(s.find(temp3) == s.end())
			continue;
		s.erase(temp2);
		s.erase(temp3);
		s.insert({temp2.l,temp3.r,temp2.len+temp3.len,temp2.value});
	}
	cout << c;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int size = 1e6 + 10;

int a[size],n;
struct segment
{
	int l,r,len,value;
};
struct classcomp
{
	bool operator() (const segment& lhs, const segment& rhs) const
	{
		if(lhs.len==rhs.len)
			return lhs.l> rhs.l;
		return lhs.len<rhs.len;
	}
};
int main()
{
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i=0;i<n;i++)
		cin >> a[i];

	vector<segment> v;
	v.push_back({0,0,1,a[0]});
	for(int i=1;i<n;i++)
	{
		if(a[i]==a[i-1])
		{
			v[v.size()-1].r=i;
			v[v.size()-1].len++;
		}
		else
			v.push_back({i,i,1,a[i]});
	}
	set<segment,classcomp> s;
	map<int,segment> left,right;
	for(auto i:v)
	{
		s.insert(i);
		left[i.l]=i;
		right[i.r]=i;
	}
	ll c=0;
	ll x;
	while(s.size())
	{
		c++;

		segment temp=*s.rbegin();
		if(s.size()==2&&n==200000)
		{
			for(auto temp:s)
				cout << temp.l << " " << temp.r << " "<<  temp.len << " " <<temp.value << endl;
		}
		s.erase(temp);
		if(temp.l==0||temp.r==n-1)
			continue;
		segment temp2=right[temp.l-1];
		segment temp3=left[temp.r+1];
		if(s.find(temp2) == s.end())
			continue;
		if(s.find(temp3) == s.end())
			continue;
		s.erase(temp2);
		if(temp2.value!=temp3.value)
		{
			temp2.r=temp3.l-1;
			s.insert(temp2);
			right[temp2.r]=temp2;
			continue;
		}
		s.erase(temp3);
		segment temp4={temp2.l,temp3.r,temp2.len+temp3.len,temp2.value};
		left[temp2.l]=temp4;
		right[temp3.r]=temp4;
		s.insert(temp4);
	}
	cout << c;

}


/*
     author : hursh29
     g++ : 17.3.20
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#define forn(i,a,b)        for( i = a ; i < b  ; i++ )
#define debug(x)           cout << #x << " " << x << "\n"
#define speedup            ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
#define ll                 long long
#define p(x) 			   cout << x << "\n" ;
#define MOD                998244353
#define pi                 pair<int,int>
#define vi                 vector <ll>
#define pb                 push_back
#define vp                 vector <pair<ll,ll>>
#define endl               cout << "\n"
#define mi                 map <int,int>
#define f1                 first
#define s1                 second
#define in                 insert
#define all(x)             x.begin(),x.end()
using namespace std ;
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,rb_tree_tag,
tree_order_statistics_node_update> indexed_set;
const int N = 1e5+7;
/*
    time : 14 : 45
    date : 25.12.2019
    Merry Christmas
*/
int t[2 * N];
int sze   ;
int C[N],D[N] ;
void build() {
  // build the tree
  for (int i = sze - 1; i > 0; --i)
   t[i] = max(t[i<<1],t[i<<1|1]);
}

void modify(int p, int value) {
  // set value at position p
  for (t[p += sze] = value; p > 1; p >>= 1)
  	t[p>>1] = max(t[p],t[p^1]);
}

int query(int l, int r) {
  // sum on interval [l, r)
  int res = 0;
  for (l += sze, r += sze; l < r; l >>= 1, r >>= 1) {
    if (l&1) res  = max(res,t[l++]);
    if (r&1) res  = max(res,t[--r]);
  }
  for(int i = 0 ;  i <= sze ; i++ )
  	if(C[i] == res )
  		return i  ;
}
const int M = 1e9+7 ;
int x,y,n,c,d ;
char a ;
int L,R,mid,idx,target ;
int max1,max2 ;
int best ,i ;
int val ;
int solve() {
    mi m1,m2 ;
	cin >> n >> c >> d ;
	vector <pi> cv,dv ;
	forn(i,0,n){
		cin >> x >> y >> a ;
		if(  a == 'C' )
			C[y] = max(C[y],x) ,m1[x]++;
		else
			D[y] = max(D[y],x) ,m2[x]++;
	}
    for(auto it : m1 )
        if(it.s1 > 1 )
        best  = max(best,2*it.f1) ;
    for(auto it : m2 )
        if(it.s1 > 1 )
        best  = max(best,2*it.f1) ;

	sze = c  ;
	forn(i,0,c)
		t[i+c] = C[i+1] ;
	build() ;

	forn(i,1,c+1)
		if(C[i])
			cv.pb({i,C[i]}),max1 = max(max1,C[i]) ;

	forn(i,1,d+1)
		if(D[i])
			dv.pb({i,D[i]}),max2 = max(max2,D[i]) ;
    if(max1 && max2)
    best = max1+max2 ;
    forn(i,0,cv.size()) {

    	target = c - cv[i].f1 ;
    	idx = -1 ;
    	L = 0,R = cv.size() ;
    	while(L <= R ){
    		mid  = L + (R-L)/2  ;
    		if(cv[mid].f1  <= target){
    			L = mid +1  ;
    			idx = mid ;
    		}
    		else
    			R = mid -1 ;
    	}
    	if(idx == -1 )
    		continue  ;
    	max1 = query(0,cv[i].f1) ;
    	val  =  C[max1] ;
    	modify(max1-1,-1) ;
    	max2 = query(0,idx) ;
    	best  = max(C[max1]+C[max2],best);
    	modify(max1-1,val) ;

    }
    sze = d  ;
	forn(i,0,d)
		t[i+d] = D[i+1] ;
	build() ;

    forn(i,0,dv.size()) {

    	target = d - dv[i].f1 ;
    	idx = -1 ;
    	L = 0,R = dv.size() ;
    	while(L <= R ){
    		mid  = L + (R-L)/2  ;
    		if(dv[mid].f1  <= target){
    			L = mid +1  ;
    			idx = mid ;
    		}
    		else
    			R = mid -1 ;
    	}
    	if(idx == -1 )
    		continue  ;
    	max1 = query(0,dv[i].f1) ;
    	val  =  D[max1] ;
    	modify(max1-1,-1) ;
    	max2 = query(0,idx) ;
    	best  = max(D[max1]+D[max2],best);
    	modify(max1-1,val) ;

    }
    p(best) ;
    return 0 ;
}
int main() {
	speedup ;
    int test  = 1 ;
	// cin >> test  ;
	while(test--)
    	solve() ;

	return 0;
}


/*
     author : hursh29
     g++ : 17.3.20
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#define forn(i,a,b)        for( i = a ; i < b  ; i++ )
#define debug(x)           cout << #x << " " << x << "\n"
#define speedup            ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
#define ll                 long long
#define p(x) 			   cout << x << "\n" ;
#define MOD                998244353
#define pi                 pair<int,int>
#define vi                 vector <ll>
#define pb                 push_back
#define vp                 vector <pair<ll,ll>>
#define endl               cout << "\n"
#define mi                 map <int,int>
#define f1                 first
#define s1                 second
#define in                 insert
#define all(x)             x.begin(),x.end()
using namespace std ;
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,rb_tree_tag,
tree_order_statistics_node_update> indexed_set;
const int N = 1e5+7;
/*
    time : 21 : 55
    date : 25.12.2019
    Merry Christmas
*/

map <int,vector <int>>  m1,m2 ;
int t[2 * N];
int sze   ;
int C[N],D[N] ;
void build() {
  // build the tree
  for (int i = sze - 1; i > 0; --i)
   t[i] = max(t[i<<1],t[i<<1|1]);
}

void modify(int p, int value) {
  // set value at position p
  for (t[p += sze] = value; p > 1; p >>= 1)
  	t[p>>1] = max(t[p],t[p^1]);
}

int query(int l, int r,bool check) {
  // sum on interval [l, r)
  int res = -1e8;
  for (l += sze, r += sze; l < r; l >>= 1, r >>= 1) {
    if (l&1) res  = max(res,t[l++]);
    if (r&1) res  = max(res,t[--r]);
  }
    if(res <= 0 )
        return -1 ;

    if(check)
    	return m1[res][0] ;

    return m2[res][0] ;

}
const int M = 1e9+7 ;
int x,y,n,c,d ,j ;
char a ;
int L,R,mid,idx,target ;
int max1,max2 ;
int best ,i ;
int val ;
int solve() {
	cin >> n >> c >> d ;
	vector <pi> cv,dv ;
	forn(i,0,n){
		cin >> x >> y >> a ;
		if(  a == 'C' )
			C[y] = max(C[y],x) ,m1[x].pb(y);
		else
			D[y] = max(D[y],x) ,m2[x].pb(y);
	}
    for(auto it : m1 )
        if(it.s1.size() > 1 ){
        	sort(all(it.s1)) ;
         if(it.s1[0] + it.s1[1] <= c )
	        best  = max(best,2*it.f1) ;
	}
    for(auto it : m2 )
        if(it.s1.size() > 1 ){
        	sort(all(it.s1)) ;
         if(it.s1[0] + it.s1[1] <= d )
	        best  = max(best,2*it.f1) ;
	}
	sze = c  ;
	forn(i,0,c)
		t[i+c] = C[i+1] ;
	build() ;

	forn(i,1,c+1)
		if(C[i])
			cv.pb({i,C[i]}),max1 = max(max1,C[i]) ;

	forn(i,1,d+1)
		if(D[i])
			dv.pb({i,D[i]}),max2 = max(max2,D[i]) ;
    if(max1 && max2)
    best = max(best,max1+max2) ;

    forn(i,0,cv.size()) {
    	/*
    	debug(cv[i].f1) ;

        cout << cv[i].s1 << " " ;
        */
    	target = c - cv[i].f1 ;
    	idx = -1 ;
    	L = 0,R = cv.size()-1 ;
    	while(L <= R ){
    		mid  = L + (R-L)/2  ;
    		if(cv[mid].f1  <= target){
    			L = mid +1  ;
    			idx = mid ;
    		}
    		else
    			R = mid -1 ;
    	}
    	if(idx == -1 )
    		continue  ;
    	max1 = query(0,cv[i].f1,1) ;
        if(max1 == -1)
            continue ;
    	/*forn(j,1,2*c)
    	cout << t[j] << " | " ;
    	endl ;*/
    	val  =  C[max1] ;
    	modify(max1-1,-1e8) ;
    	max2 = query(0,cv[idx].f1,1) ;
        /*	forn(j,1,2*c)
    	  cout << t[j] << " | " ;
    	endl ;*/
        if(max2 == -1 ){
        	modify(max1-1 ,val) ;
            continue ;
        }
        // debug(C[max1]+C[max2]) ;
    	best  = max(C[max1]+C[max2],best);
    	modify(max1-1 ,val) ;
    	/*	forn(j,1,2*c)
    	 cout << t[j] << " | " ;
    	endl ;
    	endl ; */

    }
    forn(i,0,2*N)
        t[i] = 0 ;
    sze = d  ;
	forn(i,0,d)
		t[i+d] = D[i+1] ;
	build() ;

    forn(i,0,dv.size()) {
    	// debug(dv[i].f1) ;
     //    cout << dv[i].s1 << " " ;
    	target = d - dv[i].f1 ;
    	idx = -1 ;
    	L = 0,R = dv.size()-1 ;
    	while(L <= R ){
    		mid  = L + (R-L)/2  ;
    		if(dv[mid].f1  <= target){
    			L = mid +1  ;
    			idx = mid ;
    		}
    		else
    			R = mid -1 ;
    	}
    	if( idx == -1 )
    		continue  ;

    	max1 = query(0,dv[i].f1,0) ;
        if(  max1 == -1 )
            continue ;
    	val  =  D[max1] ;
		// forn(j,d,2*d)
	 //    	cout << t[j] << " | " ;
  //   	endl ;
    	modify(max1-1,-1e8) ;

    	max2 = query(0,dv[idx].f1,0) ;
          if(  max2 == -1 ){
              modify(max1-1,val) ;
               continue ; }
		// forn(j,d,2*d)
		// cout << t[j] << " | " ;
		// endl ;

        // debug(D[max1]+D[max2]) ;
    	best  = max(D[max1]+D[max2],best);
    	modify(max1-1,val) ;
    	// forn(j,d,2*d)
    	// cout << t[j] << " | " ;
    	// endl ;
    	// endl ;

    }
    p(best) ;
    return 0 ;
}
int main() {
	speedup ;
    int test  = 1 ;
	// cin >> test  ;
	while(test--)
    	solve() ;

	return 0;
}


// Sat Nov  7 20:13:51 IST 2020
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#define forn(ii, a, b) for (int ii = a; ii < b; ii++)
#define scan(any)      for (auto &i : any) cin >> i;
#define debug(x)       cerr << #x << " " << x << " -- \n"
#define I__O           ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define int64          long long
#define all(x)         (x).begin(), (x).end()
#define ff             first
#define ss             second
#define p32            pair<int,int>
#define p64            pair<int64,int64>
#define precise(x)     cout << fixed << setprecision(12) << x << '\n';
using namespace std;
// policy based
using namespace __gnu_pbds;
template <class T> using indexed_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
const int MOD1 = 1e9 + 7;
const int MOD2 = 1e9 + 9;
const int64 weird_mod = 998244353;
const double pi = 3.141592653589793238;
const int INF = 2e7 + 7;
const int64 big = 1e18;

const int N = 2e5 + 7;
struct compare
{
    bool operator()(pair<int, int> A, pair<int, int> B)
    {
        if (A.first == B.first)
            return A.second > B.second;
        return A.first > B.first;
    }
};
template <typename T>
void print(T v)
{
    for (auto t : v)
        cout << t << ' ';
    cout << '\n';
    return;
}
int64 fast_exponentiaion(int n, int64 x, int MOD){
    if (n == 0)
        return 1LL;
    int64 half = fast_exponentiaion(n / 2, x, MOD);
    if ((n & 1) ^ 1)
        return (half*half)%MOD;
    return (((half*half)%MOD)*x)%MOD;
}
int64 inverse(int64 a){
    return fast_exponentiaion(MOD1 - 2, a % MOD1, MOD1);
}

class SegmentTree
{
        int n;
        vector<int> t;
    public:
        SegmentTree(vector<int> vec)
        {
            n = vec.size();
            t = vector<int>(2 * n);
            for (int i = n; i < 2 * n; i++)
                t[i] = vec[i - n];
            for (int i = n - 1; ~i; i--)
                t[i] = t[i << 1] + t[i << 1 | 1];
        }
        void modify(int p, int value)
        {
            for (t[p += n] = value; p > 1; p >>= 1)
                t[p >> 1] = t[p] + t[p ^ 1] ;
        }
        int query(int l, int r)
        {
            int res = 0;
            for (l += n, r += n; l < r; l >>= 1, r >>= 1)
            {
                if (l & 1)
                    res += t[l++];
                if (r & 1)
                    res += t[--r];
            }
            return res;
        }
};
#define mat vector <vector <int64>>
mat operator*(mat m1, mat m2){
    vector <vector <int64>> res(6,vector <int64> (6,0));
    forn(i,0,6)
        forn(j,0,6){
            int64 s = 0;
            forn(k,0,6)
                s = (s + (m1[i][k]*m2[k][j])%MOD1)%MOD1;
            res[i][j] = s;
        }
    return res;
}
mat base_case;
mat matrix_exponentiation(int64 n){
    if(n == 1){
        return base_case;
    }
    mat result = matrix_exponentiation(n/2);
    if(n&1)
        return base_case*(result*result);
    return (result*result);
}
int  test(){
    int n,c,d;
    cin >> n >> c >> d;
    vector <int> coins(c+1),diamonds(d+1);
    int best = 0;
    vector <int> C[c+1],D[d+1];
    while(n--){
        int b,cost; char type;
        cin >> b >> cost >> type;
        if(type == 'C' && cost <= c){
            if(coins[cost] >  0){
                if(cost*2 <= c){
                    best =  max(best,coins[cost] + b);
                }
            }
            C[cost].push_back(b);
            coins[cost] = max(coins[cost],b);
        }
        else if(type == 'D' && cost <= d){
            if(diamonds[cost] >  0){
                if(cost*2 <= d){
                    best =  max(best,diamonds[cost] + b);
                }
            }
            D[cost].push_back(b);
            diamonds[cost] = max(diamonds[cost],b);
        }
    }
    forn(i,1,d+1)
        if(D[i].size() > 1){
        sort(D[i].rbegin(), D[i].rend());
        best = max(best,D[i][0] + D[i][1]);
    }
    forn(i,1,c+1)
        if(C[i].size() > 1){
        sort(C[i].rbegin(), C[i].rend());
        best = max(best,C[i][0] + C[i][1]);
    }
    // print(coins);
    // print(diamonds);
    for(int i = 1 ; i <= c ; i++){
        if(i > c-i && coins[i] && coins[c-i])
            best = max(best,coins[i] + coins[c-i]);
        debug(best);
        coins[i] = max(coins[i-1],coins[i]);
    }
    for(int i = 1 ; i <= d ; i++){
        if(i > d-i && diamonds[i] && diamonds[d-i] )
            best = max(best,diamonds[i] + diamonds[d-i]);
        debug(best);
        diamonds[i] = max(diamonds[i-1],diamonds[i]);
    }
    sort(coins.rbegin(), coins.rend());
    sort(diamonds.rbegin(), diamonds.rend());
    if(coins[0] >  0 && diamonds[0] > 0) {
        best = max(best, coins[0] + diamonds[0]);
    }
    cout << best << '\n';
    return 0;
}
int32_t main()
{
    I__O;
    int cases = 1;
    // cin >> cases;
    while(cases--)
        test();

    return 0LL;
}


/*
     author : hursh29
     g++ : 17.3.20
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#define forn(i,a,b)        for( i = a ; i < b  ; i++ )
#define debug(x)           cout << #x << " " << x << "\n"
#define speedup            ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
#define ll                 long long
#define p(x) 			   cout << x << "\n" ;
#define MOD                998244353
#define pi                 pair<int,int>
#define vi                 vector <ll>
#define pb                 push_back
#define vp                 vector <pair<ll,ll>>
#define endl               cout << "\n"
#define mi                 map <int,int>
#define f1                 first
#define s1                 second
#define in                 insert
#define all(x)             x.begin(),x.end()
using namespace std ;
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,rb_tree_tag,
tree_order_statistics_node_update> indexed_set;
const int N = 1e5+7;
/*
    time : 14 : 45
    date : 25.12.2019
    Merry Christmas
*/
int t[2 * N];
int sze   ;
int C[N],D[N] ;
void build() {
  // build the tree
  for (int i = sze - 1; i > 0; --i)
   t[i] = max(t[i<<1],t[i<<1|1]);
}

void modify(int p, int value) {
  // set value at position p
  for (t[p += sze] = value; p > 1; p >>= 1)
  	t[p>>1] = max(t[p],t[p^1]);
}

int query(int l, int r) {
  // sum on interval [l, r)
  int res = 0;
  for (l += sze, r += sze; l < r; l >>= 1, r >>= 1) {
    if (l&1) res  = max(res,t[l++]);
    if (r&1) res  = max(res,t[--r]);
  }
  for(int i = 0 ;  i <= sze ; i++ )
  	if(C[i] == res )
  		return i  ;
}
const int M = 1e9+7 ;
int x,y,n,c,d ;
char a ;
int L,R,mid,idx,target ;
int max1,max2 ;
int best ,i ;
int val ;
int solve() {
	cin >> n >> c >> d ;
	vector <pi> cv,dv ;
	forn(i,0,n){
		cin >> x >> y >> a ;
		if(  a == 'C' )
			C[y] = max(C[y],x) ;
		else
			D[y] = max(D[y],x) ;
	}

	sze = c  ;
	forn(i,0,c)
		t[i+c] = C[i+1] ;
	build() ;

	forn(i,1,c+1)
		if(C[i])
			cv.pb({i,C[i]}),max1 = max(max1,C[i]) ;

	forn(i,1,d+1)
		if(D[i])
			dv.pb({i,D[i]}),max2 = max(max2,D[i]) ;
    if(max1 && max2)
    best = max1+max2 ;
    forn(i,0,cv.size()) {

    	target = c - cv[i].f1 ;
    	idx = -1 ;
    	L = 0,R = cv.size() ;
    	while(L <= R ){
    		mid  = L + (R-L)/2  ;
    		if(cv[mid].f1  <= target){
    			L = mid +1  ;
    			idx = mid ;
    		}
    		else
    			R = mid -1 ;
    	}
    	if(idx == -1 )
    		continue  ;
    	max1 = query(0,cv[i].f1) ;
    	val  =  C[max1] ;
    	modify(max1-1,-1) ;
    	max2 = query(0,idx) ;
    	best  = max(C[max1]+C[max2],best);
    	modify(max1-1,val) ;

    }
    sze = d  ;
	forn(i,0,d)
		t[i+d] = D[i+1] ;
	build() ;

    forn(i,0,dv.size()) {

    	target = d - dv[i].f1 ;
    	idx = -1 ;
    	L = 0,R = dv.size() ;
    	while(L <= R ){
    		mid  = L + (R-L)/2  ;
    		if(dv[mid].f1  <= target){
    			L = mid +1  ;
    			idx = mid ;
    		}
    		else
    			R = mid -1 ;
    	}
    	if(idx == -1 )
    		continue  ;
    	max1 = query(0,dv[i].f1) ;
    	val  =  D[max1] ;
    	modify(max1-1,-1) ;
    	max2 = query(0,idx) ;
    	best  = max(D[max1]+D[max2],best);
    	modify(max1-1,val) ;

    }
    p(best) ;
    return 0 ;
}
int main() {
	speedup ;
    int test  = 1 ;
	// cin >> test  ;
	while(test--)
    	solve() ;

	return 0;
}


/*
     author : hursh29
     g++ : 17.3.20
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#define forn(i,a,b)        for( i = a ; i < b  ; i++ )
#define debug(x)           cout << #x << " " << x << "\n"
#define speedup            ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
#define ll                 long long
#define p(x) 			   cout << x << "\n" ;
#define MOD                998244353
#define pi                 pair<int,int>
#define vi                 vector <ll>
#define pb                 push_back
#define vp                 vector <pair<ll,ll>>
#define endl               cout << "\n"
#define mi                 map <int,int>
#define f1                 first
#define s1                 second
#define in                 insert
#define all(x)             x.begin(),x.end()
using namespace std ;
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,rb_tree_tag,
tree_order_statistics_node_update> indexed_set;
const int N = 1e5+7;
/*
    time : 14 : 45
    date : 25.12.2019
    Merry Christmas
*/
int t[2 * N];
int sze   ;
int C[N],D[N] ;
void build() {
  // build the tree
  for (int i = sze - 1; i > 0; --i)
   t[i] = max(t[i<<1],t[i<<1|1]);
}

void modify(int p, int value) {
  // set value at position p
  for (t[p += sze] = value; p > 1; p >>= 1)
  	t[p>>1] = max(t[p],t[p^1]);
}

int query(int l, int r) {
  // sum on interval [l, r)
  int res = 0;
  for (l += sze, r += sze; l < r; l >>= 1, r >>= 1) {
    if (l&1) res  = max(res,t[l++]);
    if (r&1) res  = max(res,t[--r]);
  }
  for(int i = 0 ;  i <= sze ; i++ )
  	if(C[i] == res )
  		return i  ;
}
const int M = 1e9+7 ;
int x,y,n,c,d ;
char a ;
int L,R,mid,idx,target ;
int max1,max2 ;
int best ,i ;
int val ;
int solve() {
    mi m1,m2 ;
	cin >> n >> c >> d ;
	vector <pi> cv,dv ;
	forn(i,0,n){
		cin >> x >> y >> a ;
		if(  a == 'C' )
			C[y] = max(C[y],x) ,m1[x]++;
		else
			D[y] = max(D[y],x) ,m2[x]++;
	}
    for(auto it : m1 )
        if(it.s1 > 1 )
        best  = max(best,2*it.f1) ;
    for(auto it : m2 )
        if(it.s1 > 1 )
        best  = max(best,2*it.f1) ;

	sze = c  ;
	forn(i,0,c)
		t[i+c] = C[i+1] ;
	build() ;

	forn(i,1,c+1)
		if(C[i])
			cv.pb({i,C[i]}),max1 = max(max1,C[i]) ;

	forn(i,1,d+1)
		if(D[i])
			dv.pb({i,D[i]}),max2 = max(max2,D[i]) ;
    if(max1 && max2)
    best = max1+max2 ;
    forn(i,0,cv.size()) {

    	target = c - cv[i].f1 ;
    	idx = -1 ;
    	L = 0,R = cv.size() ;
    	while(L <= R ){
    		mid  = L + (R-L)/2  ;
    		if(cv[mid].f1  <= target){
    			L = mid +1  ;
    			idx = mid ;
    		}
    		else
    			R = mid -1 ;
    	}
    	if(idx == -1 )
    		continue  ;
    	max1 = query(0,cv[i].f1) ;
    	val  =  C[max1] ;
    	modify(max1-1,-1) ;
    	max2 = query(0,idx) ;
    	best  = max(C[max1]+C[max2],best);
    	modify(max1-1,val) ;

    }
    forn(i,0,2*N)
        t[i] = 0 ;
    sze = d  ;
	forn(i,0,d)
		t[i+d] = D[i+1] ;
	build() ;

    forn(i,0,dv.size()) {

    	target = d - dv[i].f1 ;
    	idx = -1 ;
    	L = 0,R = dv.size() ;
    	while(L <= R ){
    		mid  = L + (R-L)/2  ;
    		if(dv[mid].f1  <= target){
    			L = mid +1  ;
    			idx = mid ;
    		}
    		else
    			R = mid -1 ;
    	}
    	if(idx == -1 )
    		continue  ;
    	max1 = query(0,dv[i].f1) ;
    	val  =  D[max1] ;
    	modify(max1-1,-1) ;
    	max2 = query(0,idx) ;
    	best  = max(D[max1]+D[max2],best);
    	modify(max1-1,val) ;

    }
    p(best) ;
    return 0 ;
}
int main() {
	speedup ;
    int test  = 1 ;
	// cin >> test  ;
	while(test--)
    	solve() ;

	return 0;
}