#include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(ary),key)-begin(ary)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
template<class T>bool chmin(T &a, const T &b) { return (b<a)?(a=b,1):0;}

using ll=long long;
using R=long double;
const R EPS=1e-9L; // [-1000,1000]->EPS=1e-8 [-10000,10000]->EPS=1e-7
inline int sgn(const R& r){return(r > EPS)-(r < -EPS);}
inline R sq(R x){return sqrt(max(x,0.0L));}

const int dx[8]={1,0,-1,0,1,-1,-1,1};
const int dy[8]={0,1,0,-1,1,1,-1,-1};

//Appropriately Changed
using G = vector<set<int>>;

//Appropriately Changed
void add_edge(G &graph, int from, int to) {
	graph[from].insert({to});
}


struct Union_find{
	Union_find(int n){par.resize(n),iota(_all(par),0);}
	int find(int x){return (par[x]==x)?x:par[x]=find(par[x]);}
	void unite(int a,int b){a=find(a),b=find(b);par[a]=b;}
	bool same(int a,int b){return find(a)==find(b);}
	vector<int> par;
};

auto topological_sort(const G& graph){
    const int n=graph.size();
    vector<int> used(n,0),order;

    auto dfs=[&](int v){
        auto func=[&](int v,auto func)->void{
            used[v]=true;
            for(auto &v2:graph[v]) if(!used[v2]) func(v2,func);
            order.push_back(v);
        };
        return func(v,func);
    };
    
    rep(v,n)if(!used[v]) dfs(v);
    reverse(_all(order));
    return order;
}

const int limit=100010;
int cost[limit];

int main(void){
	int n;
	cin >> n;
	vector<int> c(n);
	rep(i,n) cin >> c[i];
	
	G graph(n);
	int m;
	cin >> m;
	rep(i,m){
		int a,b;
		cin >> a >> b;
		a--,b--;
		add_edge(graph,a,b);
		add_edge(graph,b,a);
	}

	Union_find uf(n);
	rep(v,n){
		using pii=pair<int,int>;
		vector<pii> ary;
		ary.push_back(pii(c[v],v));
		
		for(auto &v2:graph[v]) ary.push_back(pii(c[v2],v2));

		sort(begin(ary),end(ary));
		const int m = ary.size();
		rep(i,m-1) if(ary[i].first == ary[i+1].first) uf.unite(ary[i].second,ary[i+1].second);
	}

	vector<int> conv;
	rep(v,n) if(uf.find(v)==v) conv.push_back(v);
	const int k = conv.size();
	G ngraph(k);

	rep(v,n){
		using pii=pair<int,int>;
		vector<pii> ary;
		ary.push_back(pii(c[v],getidx(conv,uf.find(v))));
		
		int pi = 0;

		for(auto &v2:graph[v]){
			ary.push_back(pii(c[v2],getidx(conv,uf.find(v2))));
		}

		sort(begin(ary),end(ary));
		const int m = ary.size();
		
		rep(i,m){
			if(i-1 >= 0 and ary[i].first != ary[i-1].first){
				pi = i-1;
			}

			if(ary[pi].first != ary[i].first){
				//cerr << "Edge: " << ary[pi].second << " " << ary[i].second << endl;
 				add_edge(ngraph,ary[pi].second,ary[i].second);
			}
		}
	
	}

	rep(v,k) cost[v] = 1;
	vector<int> order = topological_sort(ngraph);
	for(auto &v:order){
		for(auto &v2:ngraph[v]){
			chmax(cost[v2],cost[v]+1);
		}
	}

	ll ans = 0LL;

	//cerr << cost[0] << " " << cost[1] << " " << cost[2] << endl;

	rep(v,n){
		//cerr << v <<  " " << getidx(conv,uf.find(v)) << endl;
		ans += cost[getidx(conv,uf.find(v))];
	}
	cout << ans << endl;

	return 0;
}

Measured memory_bytes: 48384