
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#define rep(i,n) for (int i = 0; i < (n); ++i)

using namespace std;


using ll = long long;
using P = pair<int, int>;

void solve_WA() {
    int N;
    cin >> N;
    vector<int> A(N + 1);
    //vector<int> ac(N + 1, 0);
    map<int, int>ac;
    /*
1 5 3 2 5 2 3 1の場合はOK ※連結成分が1のみ
1 5 3 2 5 4 6 1の場合はNG ※連結成分が2以上
    
    */
    for (size_t i = 1; i < N+1; i++)
    {
        cin >> A[i];
    }
    int l, r;
    int m = N / 2;
    for ( l = 1,r=N; l <= m; l++, r--)
    {
        if (A[l] != A[r]) {
            ac[A[l]]++;
            ac[A[r]]++;
        }
    }
    //vector<P> co;
    int ans = 0;
    if (N == 1 || ac.size() == 0) {
        ans = 0;
    }
    else {

        ans = ac.size() - 1;
    }
    cout << ans << endl;

    //return 0;
}

template <typename T>
struct UnionFind {
    vector<T> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

    UnionFind(T N) : par(N) { //最初は全てが根であるとして初期化
        for (T i = 0; i < N; i++) par[i] = i;
    }

    int root(T x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }

    void unite(T x, T y) { // xとyの木を併合
        T rx = root(x); //xの根をrx
        T ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
    }

    bool same(T x, T y) { // 2つのデータx, yが属する木が同じならtrueを返す
        T rx = root(x);
        T ry = root(y);
        return rx == ry;
    }
    vector<vector<T>> linked_group() {
        vector<vector<T>> group(par.size());
        for (T i = 0; i < par.size(); i++)
        {
            T r = root(par[i]);
            group[r].emplace_back(i);
        }
        return group;
    }
};

void solve() {
    int N;
    cin >> N;
    vector<int> A(N + 1);
    map<int, int>ac;
    for (size_t i = 1; i < N + 1; i++)
    {
        cin >> A[i];
    }
    int l, r;
    int m = N / 2;
    UnionFind<int> uf(2*1e5+1);
    for (l = 1, r = N; l <= m; l++, r--)
    {
        if (A[l] != A[r]) {
            uf.unite(A[l], A[r]);
        }
    }
    vector<vector<int>> lg = uf.linked_group();
    int ans = 0;
    for (auto g : lg) {
        if (1 < g.size()) {
            ans += g.size() - 1;
        }
    }
    cout << ans << endl;
}

int main()
{
    solve();
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define MOD2 998244353
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define reps(i,s,n) for (int i = (int)(s); i < (int)(n); i++)
#define pr(a) cout << a
#define prl(a) cout << (a) << endl
#define prld(a) cout << setprecision(15)<< (a) << endl 
#define allrange(a) a.begin(),a.end()

struct GrowedUnionFind {
    std::unordered_map<int,int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    std::unordered_set<int> keys;
    int ccnum; //連結成分の個数
 
    GrowedUnionFind():par(),keys(){ ccnum =0;}
    
    void insert(int x)
    {
      if(!find(x)){
        keys.insert(x);
        par[x]=x;
        ccnum++;
      }
    }
 
    bool find(int x) //元が入っているか探す。平均o(1)
    {
      return keys.count(x)==1;
    }
  
    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }
 
    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        ccnum--;
    }
 
    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }
};


int main(){
    std::cin.tie(0); // cinとcoutの同期を解除
    std::ios::sync_with_stdio(false);
    //1変数入力
    int N;
    cin >> N;
    bool flg=false;
    int ans;

    vector<int> A(N/2);
    vector<int> B(N/2);
    int j = N%2;//パリティ
    rep(i,N){
        if(i<N/2)
            cin >> A[i];
        else if(i>=N/2+j)
            cin >> B[i-N/2-j];
        else if(j==1 && i == N/2) cin >> ans; //捨て 
    }
    ans=0;

    reverse(allrange(A));
    int n = N/2;

    GrowedUnionFind V;
    rep(i,n){
        if(A[i] != B[i])
        { V.insert(A[i]);V.insert(B[i]);V.unite(A[i],B[i]);}
    } 
    
    //次数1の頂点はつぶせる
    //triangleが多くつぶせるといい
    //写像で頂点をつぶす射影写像の合成回数の問題
    //射影写像自体は可換なので, 実は順番はあまり関係ない
    //非連結成分はくっつける必要はない.　
    //連結成分同士を1点に潰せればいい.
    // 頂点数-連結成分の個数
    
     ans = V.keys.size()-V.ccnum;


    flg = true;
    if(flg) prl(ans);
    else prl(-1);
}
