#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <hash_map>
#include <map>
#include <hash_set>
#include <set>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long LL;
#define mems(arr, val) memset(arr, val, sizeof(arr));
#define iterat(A) A.begin(), A.end()
#define forn(from, to) for(int i = from; i < to; ++i)
#define INF 2000000000

struct skobka
{
	char val;
	int pos;
};

pair<int, int> go(string str)
{
		stack<skobka> S;
	int max_value = -1, max_count = 0;
	int cur_count = 0;
	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] == '(')
		{
			skobka new_s;
			new_s.pos = i;
			new_s.val = '(';
			S.push(new_s);
		}
		else
		{
			if (S.size() > 0)
			{
				cur_count += 2;
				if (cur_count == max_value)
				{
					max_count++;
				}
				if (cur_count > max_value)
				{
					max_value = cur_count;
					max_count = 1;
				}
				S.pop();
			}
			else
			{
				cur_count = 0;
				cur_count = 0;
			}

		}
	}
	if (max_value == -1 && max_count == 0)
	{
		max_value = 0;
		max_count = 1;
	}
	return make_pair(max_value, max_count);
}

int main()
{
	//freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
	string str;
	cin>>str;
	stack<skobka> S;

	auto p1 = go(str);
	reverse(str.begin(), str.end());
	auto p2 = go(str);

	auto p = p1.first < p2.first ? p1 : p2;

	cout<<p.first<<" "<<p.second;
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <hash_map>
#include <map>
#include <hash_set>
#include <set>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long LL;
#define mems(arr, val) memset(arr, val, sizeof(arr));
#define iterat(A) A.begin(), A.end()
#define forn(from, to) for(int i = from; i < to; ++i)
#define INF 2000000000

struct skobka
{
	char val;
	int pos;
};

int main()
{
	//freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
	string str;
	cin>>str;
	stack<skobka> S;
	int max_value = -1, max_count = 0;
	int cur_count = 0;
	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] == '(')
		{
			skobka new_s;
			new_s.pos = i;
			new_s.val = '(';
			S.push(new_s);
		}
		else
		{
			if (S.size() > 0)
			{
				cur_count += 2;
				if (cur_count == max_value)
				{
					max_count++;
				}
				if (cur_count > max_value)
				{
					max_value = cur_count;
					max_count = 1;
				}
				S.pop();
			}
			else
			{
				cur_count = 0;
				cur_count = 0;
			}

		}
	}
	if (max_value == -1 && max_count == 0)
	{
		max_value = 0;
		max_count = 1;
	}

	cout<<max_value<<" "<<max_count;
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <hash_map>
#include <map>
#include <hash_set>
#include <set>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long LL;
#define mems(arr, val) memset(arr, val, sizeof(arr));
#define iterat(A) A.begin(), A.end()
#define forn(from, to) for(int i = from; i < to; ++i)
#define INF 2000000000

struct skobka
{
	char val;
	int pos;
};

int main()
{
	//freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
	string str;
	cin>>str;
	stack<int> S;
	vector<int> p(str.length());
	int max_val = 0, max_count = 1;
	S.push(-1);
	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] == '(')
		{
			S.push(i);
		}
		else
		{
			if (S.size() != 0) S.pop();

			if (S.size() > 0)
			{
				int tmp = i - S.top();
				if (tmp > max_val)
				{
					max_val = tmp;
					max_count = 1;
				}
				else
				{
					if (tmp == max_val)
					{
						max_count++;
					}
				}
			}

			if (S.size() == 0) S.push(i);
		}
	}

	cout<<max_val<<" "<<max_count;
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <hash_map>
#include <map>
#include <hash_set>
#include <set>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long LL;
#define mems(arr, val) memset(arr, val, sizeof(arr));
#define iterat(A) A.begin(), A.end()
#define forn(from, to) for(int i = from; i < to; ++i)
#define INF 2000000000

struct skobka
{
	char val;
	int pos;
};

pair<int, int> go(string str)
{
		stack<skobka> S;
	int max_value = -1, max_count = 0;
	int cur_count = 0;
	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] == '(')
		{
			skobka new_s;
			new_s.pos = i;
			new_s.val = '(';
			S.push(new_s);
		}
		else
		{
			if (S.size() > 0)
			{
				cur_count += 2;
				if (cur_count == max_value)
				{
					max_count++;
				}
				if (cur_count > max_value)
				{
					max_value = cur_count;
					max_count = 1;
				}
				S.pop();
			}
			else
			{
				cur_count = 0;
				cur_count = 0;
			}

		}
	}
	if (max_value == -1 && max_count == 0)
	{
		max_value = 0;
		max_count = 1;
	}
	return make_pair(max_value, max_count);
}

int main()
{
	//freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
	string str;
	cin>>str;
	stack<skobka> S;

	auto p1 = go(str);
	reverse(str.begin(), str.end());
	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] == ')') str[i] = '('; else str[i] = ')';
	}
	auto p2 = go(str);

	auto p = p1.first < p2.first ? p1 : p2;

	if (p1.first == p2.first) p.second = max(p1.second, p2.second);
	cout<<p.first<<" "<<p.second;
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <hash_map>
#include <map>
#include <hash_set>
#include <set>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long LL;
#define mems(arr, val) memset(arr, val, sizeof(arr));
#define iterat(A) A.begin(), A.end()
#define forn(from, to) for(int i = from; i < to; ++i)
#define INF 2000000000

struct skobka
{
	char val;
	int pos;
};

pair<int, int> go(string str)
{
		stack<skobka> S;
	int max_value = -1, max_count = 0;
	int cur_count = 0;
	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] == '(')
		{
			skobka new_s;
			new_s.pos = i;
			new_s.val = '(';
			S.push(new_s);
		}
		else
		{
			if (S.size() > 0)
			{
				cur_count += 2;
				if (cur_count == max_value)
				{
					max_count++;
				}
				if (cur_count > max_value)
				{
					max_value = cur_count;
					max_count = 1;
				}
				S.pop();
			}
			else
			{
				cur_count = 0;
				cur_count = 0;
			}

		}
	}
	if (max_value == -1 && max_count == 0)
	{
		max_value = 0;
		max_count = 1;
	}
	return make_pair(max_value, max_count);
}

int main()
{
	//freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
	string str;
	cin>>str;
	stack<skobka> S;

	auto p1 = go(str);
	reverse(str.begin(), str.end());
	auto p2 = go(str);

	auto p = p1.first < p2.first ? p1 : p2;

	if (p1.first == p2.first) p.second = max(p1.second, p2.second);
	cout<<p.first<<" "<<p.second;
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <hash_map>
#include <map>
#include <hash_set>
#include <set>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long LL;
#define mems(arr, val) memset(arr, val, sizeof(arr));
#define iterat(A) A.begin(), A.end()
#define forn(from, to) for(int i = from; i < to; ++i)
#define INF 2000000000

struct skobka
{
	char val;
	int pos;
};

int main()
{
	//freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
	string str;
	cin>>str;
	stack<int> S;
	vector<int> p(str.length());
	int max_val = 0, max_count = 1;
	S.push(-1);
	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] == '(')
		{
			S.push(i);
		}
		else
		{
			if (S.size() != 0) S.pop();
			if (S.size() > 0)
			{
				int tmp = i - S.top();
				if (tmp > max_val)
				{
					max_val = tmp;
					max_count = 1;
				}
				else
				{
					if (tmp == max_val)
					{
						max_count++;
					}
				}
			}
		}
	}

	cout<<max_val<<" "<<max_count;
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include<iostream>
#include<fstream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<list>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<string>
#include<sstream>
#include<time.h>
#include<numeric>
#include<functional>

using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#define INF  ((1 << 31) - 1)
#define LLINF  ((ll)((1LL << 63) - 1))
#define eps 0.00000001
#define million 1000000
#define PI 3.14159265358979323846
#define sz(v) ((int)(v).size())
#define MP make_pair
#define PB push_back
#define all(v) (v).begin(), (v).end()
typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	stack<pair<int, int> > st;
	char buf[million+10];
	scanf("%s",buf);
	string s = string(buf);
	int m = 0;
	int n = 1;
	int sum = 0;
	vector<int> start(2*million + 10, -1);
	vector<int> num(million + 10, 0);
	for (int i = 0; i < s.size(); ++i) {
		if (s[i] == '(') {
			if (start[million+sum] == -1)
				start[million+sum] = i;
			//st.push(MP(sum, i));
			++sum;
		} else {
			--sum;
			/*while(!st.empty() && st.top().first > sum) {
				int len = i - st.top().second;
				st.pop();
				if (m < len) {
					m = len;
					n = 0;
				}
				if (m == len)
					++n;
			}	*/
			if (start[million+sum] != -1) {
				++num[1+i - start[million+sum]];
			}
			start[million+sum + 1] = -1;
		}
	}
	num[0] = 1;
	for (int m = num.size() - 1; m >= 0; --m) {
		if (num[m] > 0) {
			cout << m << " " << num[m] << "\n";
			return 0;
		}
	}
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include<iostream>
#include<fstream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<list>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<string>
#include<sstream>
#include<time.h>
#include<numeric>
#include<functional>

using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#define INF  ((1 << 31) - 1)
#define LLINF  ((ll)((1LL << 63) - 1))
#define eps 0.00000001
#define million 1000000
#define PI 3.14159265358979323846
#define sz(v) ((int)(v).size())
#define MP make_pair
#define PB push_back
#define all(v) (v).begin(), (v).end()
typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	stack<pair<int, int> > st;
	char buf[million+10];
	scanf("%s",buf);
	string s = string(buf);
	int m = 0;
	int n = 1;
	int sum = 0;
	vector<int> start(2*million + 10, -1);
	vector<int> num(million + 10, 0);
	//st.push(MP(0,0));
	for (int i = 0; i < s.size(); ++i) {
		if (s[i] == '(') {
			if (start[million+sum] == -1)
				start[million+sum] = i;
			st.push(MP(sum, i));
			++sum;
		} else {
			--sum;
			pair<int, int> last = MP(-1, -1);
			while(!st.empty() && st.top().first >= sum) {
				int len = -1;
				if (st.top().first == sum) {
					len = i - st.top().second + 1;
					last = st.top();
				}
				st.pop();
				if (m < len) {
					m = len;
					n = 0;
				}
				if (m == len)
					++n;
			}
			if(last.second >= 0)
				st.push(last);
			//if (start[million+sum] != -1) {
			//	++num[1+i - start[million+sum]];
			//}
			//start[million+sum + 1] = -1;
		}
	}
	cout << m << " " << n << "\n";
	/*
	num[0] = 1;
	for (int m = num.size() - 1; m >= 0; --m) {
		if (num[m] > 0) {
			cout << m << " " << num[m] << "\n";
			return 0;
		}
	}*/
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include<iostream>
#include<fstream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<list>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<string>
#include<sstream>
#include<time.h>
#include<numeric>
#include<functional>

using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#define INF  ((1 << 31) - 1)
#define LLINF  ((ll)((1LL << 63) - 1))
#define eps 0.00000001
#define million 1000000
#define PI 3.14159265358979323846
#define sz(v) ((int)(v).size())
#define MP make_pair
#define PB push_back
#define all(v) (v).begin(), (v).end()
typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	stack<pair<int, int> > st;
	char buf[million+10];
	scanf("%s",buf);
	string s = string(buf);
	int m = 0;
	int n = 1;
	int sum = 0;
	//vector<int> start(2*million + 10, -1);
	//vector<int> num(million + 10, 0);
	for (int i = 0; i < s.size(); ++i) {
		if (s[i] == '(') {
			//if (start[million+sum] == -1)
			//	start[million+sum] = i;
			st.push(MP(sum, i));
			++sum;
		} else {
			--sum;
			//if(!st.empty() && st.top().first == sum) {
				int len = i - st.top().second + 1;
				st.pop();
				if (m < len) {
					m = len;
					n = 0;
				}
				if (m == len)
					++n;
			//}
			//if (start[million+sum] != -1) {
			//	++num[1+i - start[million+sum]];
		//	}
			//start[million+sum + 1] = -1;
		}
	}
	/*num[0] = 1;
	//for (int m = num.size() - 1; m >= 0; --m) {
		if (num[m] > 0) {
			cout << m << " " << num[m] << "\n";
			return 0;
		}
	}*/
	cout << m << " " << n << "\n";
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include<iostream>
#include<fstream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<list>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<string>
#include<sstream>
#include<time.h>
#include<numeric>
#include<functional>

using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#define INF  ((1 << 31) - 1)
#define LLINF  ((ll)((1LL << 63) - 1))
#define eps 0.00000001
#define million 1000000
#define PI 3.14159265358979323846
#define sz(v) ((int)(v).size())
#define MP make_pair
#define PB push_back
#define all(v) (v).begin(), (v).end()
typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	stack<pair<int, int> > st;
	char buf[million+10];
	scanf("%s",buf);
	string s = string(buf);
	int m = 0;
	int n = 1;
	int sum = 0;
	s = s + ')';
	for (int i = 0; i < s.size(); ++i) {
		if (s[i] == '(') {
			st.push(MP(sum, i));
			++sum;
		} else {
			--sum;
			while(!st.empty() && st.top().first > sum) {
				int len = i - st.top().second;
				if (m < len) {
					m = len;
					n = 0;
				}
				if (m == len)
					++n;
				st.pop();
			}
		}
	}
	cout << m << " " << n << "\n";
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include<iostream>
#include<fstream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<list>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<string>
#include<sstream>
#include<time.h>
#include<numeric>
#include<functional>

using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#define INF  ((1 << 31) - 1)
#define LLINF  ((ll)((1LL << 63) - 1))
#define eps 0.00000001
#define million 1000000
#define PI 3.14159265358979323846
#define sz(v) ((int)(v).size())
#define MP make_pair
#define PB push_back
#define all(v) (v).begin(), (v).end()
typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	stack<pair<int, int> > st;
	char buf[million+10];
	scanf("%s",buf);
	string s = string(buf);
	int m = 0;
	int n = 1;
	int sum = 0;
	vector<int> start(2*million, -1);
	vector<int> num(million, 0);
	for (int i = 0; i < s.size(); ++i) {
		if (s[i] == '(') {
			if (start[million+sum] == -1)
				start[million+sum] = i;
			//st.push(MP(sum, i));
			++sum;
		} else {
			--sum;
			/*while(!st.empty() && st.top().first > sum) {
				int len = i - st.top().second;
				st.pop();
				if (m < len) {
					m = len;
					n = 0;
				}
				if (m == len)
					++n;
			}	*/
			if (start[million+sum] != -1) {
				++num[1+i - start[million+sum]];
			}
			start[million+sum + 1] = -1;
		}
	}
	num[0] = 1;
	for (int m = num.size() - 1; m >= 0; --m) {
		if (num[m] > 0) {
			cout << m << " " << num[m] << "\n";
			return 0;
		}
	}
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include<iostream>
#include<fstream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<list>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<string>
#include<sstream>
#include<time.h>
#include<numeric>
#include<functional>

using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#define INF  ((1 << 31) - 1)
#define LLINF  ((ll)((1LL << 63) - 1))
#define eps 0.00000001
#define million 1000000
#define PI 3.14159265358979323846
#define sz(v) ((int)(v).size())
#define MP make_pair
#define PB push_back
#define all(v) (v).begin(), (v).end()
typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	stack<pair<int, int> > st;
	char buf[million+10];
	scanf("%s",buf);
	string s = string(buf);
	int m = 0;
	int n = 1;
	int sum = 0;
	//vector<int> start(2*million + 10, -1);
	//vector<int> num(million + 10, 0);
	for (int i = 0; i < s.size(); ++i) {
		if (s[i] == '(') {
			//if (start[million+sum] == -1)
			//	start[million+sum] = i;
			st.push(MP(sum, i));
			++sum;
		} else {
			--sum;
			if(!st.empty()) {
				int len = i - st.top().second + 1;
				st.pop();
				if (m < len) {
					m = len;
					n = 0;
				}
				if (m == len)
					++n;
			}
			//if (start[million+sum] != -1) {
			//	++num[1+i - start[million+sum]];
		//	}
			//start[million+sum + 1] = -1;
		}
	}
	/*num[0] = 1;
	//for (int m = num.size() - 1; m >= 0; --m) {
		if (num[m] > 0) {
			cout << m << " " << num[m] << "\n";
			return 0;
		}
	}*/
	cout << m << " " << n << "\n";
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include<iostream>
#include<fstream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<list>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<string>
#include<sstream>
#include<time.h>
#include<numeric>
#include<functional>

using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#define INF  ((1 << 31) - 1)
#define LLINF  ((ll)((1LL << 63) - 1))
#define eps 0.00000001
#define million 1000000
#define PI 3.14159265358979323846
#define sz(v) ((int)(v).size())
#define MP make_pair
#define PB push_back
#define all(v) (v).begin(), (v).end()
typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	stack<pair<int, int> > st;
	char buf[million+10];
	scanf("%s",buf);
	string s = string(buf);
	int m = 0;
	int n = 1;
	int sum = 0;
	//vector<int> start(2*million + 10, -1);
	//vector<int> num(million + 10, 0);
	for (int i = 0; i < s.size(); ++i) {
		if (s[i] == '(') {
			//if (start[million+sum] == -1)
			//	start[million+sum] = i;
			st.push(MP(sum, i));
			++sum;
		} else {
			--sum;
			if(!st.empty() && st.top().first == sum) {
				int len = i - st.top().second + 1;
				st.pop();
				if (m < len) {
					m = len;
					n = 0;
				}
				if (m == len)
					++n;
			}
			//if (start[million+sum] != -1) {
			//	++num[1+i - start[million+sum]];
		//	}
			//start[million+sum + 1] = -1;
		}
	}
	/*num[0] = 1;
	//for (int m = num.size() - 1; m >= 0; --m) {
		if (num[m] > 0) {
			cout << m << " " << num[m] << "\n";
			return 0;
		}
	}*/
	cout << m << " " << n << "\n";
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include<iostream>
#include<fstream>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<list>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<string>
#include<sstream>
#include<time.h>
#include<numeric>
#include<functional>

using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#define INF  ((1 << 31) - 1)
#define LLINF  ((ll)((1LL << 63) - 1))
#define eps 0.00000001
#define million 1000000
#define PI 3.14159265358979323846
#define sz(v) ((int)(v).size())
#define MP make_pair
#define PB push_back
#define all(v) (v).begin(), (v).end()
typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	stack<pair<int, int> > st;
	char buf[million+10];
	scanf("%s",buf);
	string s = string(buf);
	int m = 0;
	int n = 1;
	int sum = 0;
	vector<int> start(2*million + 10, -1);
	vector<int> num(million + 10, 0);
	st.push(MP(0,0));
	for (int i = 0; i < s.size(); ++i) {
		if (s[i] == '(') {
			if (start[million+sum] == -1)
				start[million+sum] = i;
			st.push(MP(sum, i));
			++sum;
		} else {
			--sum;
			if(!st.empty() && st.top().first == sum) {
				st.pop();
				int len = i - st.top().second + 1;
				if (m < len) {
					m = len;
					n = 0;
				}
				if (m == len)
					++n;
			}
			//if (start[million+sum] != -1) {
			//	++num[1+i - start[million+sum]];
			//}
			//start[million+sum + 1] = -1;
		}
	}
	cout << m << " " << n << "\n";
	/*
	num[0] = 1;
	for (int m = num.size() - 1; m >= 0; --m) {
		if (num[m] > 0) {
			cout << m << " " << num[m] << "\n";
			return 0;
		}
	}*/
	return 0;
}


#include <iostream>

struct ab{int st,ta;} data[1000000];
struct cd{int v,z;} zhan[1000000];
int len,rec,pp,wz,n;

void push(char a, int b)
{
     int t=1; zhan[++n].z=b;
     if (a=='(') zhan[n].v=0;
        else zhan[n].v=1;
     if (b==1) return;
     if (zhan[n].v==0) return;
     if (zhan[n-1].v==1) return;
     data[++pp].st=zhan[n-1].z; data[pp].ta=zhan[n].z;
     while ((t!=0) && (pp>1))
     {
           t=0;
           while (data[pp-1].ta==data[pp].st-1)
           {
                 t++; data[pp-1].ta=data[pp].ta; pp--;
           };
           while ((data[pp-1].st<data[pp].st) && (data[pp-1].ta>data[pp].ta))
           {
                 t++; pp--;
           };
           while ((data[pp].st<data[pp-1].st) && (data[pp].ta>data[pp-1].ta))
           {
                 t++; data[pp-1]=data[pp]; pp--;
           }
     };
     n-=2;
     return;
};

void check()
{
     int i,l;
     for (i=1; i<=pp; i++)
     {
         l=data[i].ta-data[i].st+1;
         if (l==len) rec++;
         if (l>len)
         {
                   len=l; rec=1;
         };
     };
};

int main()
{
     //freopen("a.in","r",stdin); freopen("a.out","w",stdout);
     len=0; pp=0; rec=1; wz=0; n=0;
     char s; s=getchar();
     while ((s=='(')||(s==')'))
     {
           wz++;
           push(s,wz);
           s=getchar();
     };
     check();
     printf("%d %d\n",len,rec);
     return 0;
};


#include <iostream>

struct ab{int st,ta;} data[1000000];
struct cd{int v,z;} zhan[1000000];
int len,rec,pp,wz,n;

void push(char a, int b)
{
     int t=1; zhan[++n].z=b;
     if (a=='(') zhan[n].v=0;
        else zhan[n].v=1;
     if (b==1) return;
     if (zhan[n].v==0) return;
     if (zhan[n-1].v==1) return;
     data[++pp].st=zhan[n-1].z; data[pp].ta=zhan[n].z;
     while ((t!=0) && (pp>1))
     {
           t=0;
           while (data[pp-1].ta==data[pp].st-1)
           {
                 t++; pp--;
                 data[pp].ta=b;
           };
           while ((data[pp-1].st<data[pp].st) && (data[pp-1].ta>data[pp].ta))
           {
                 t++; pp--;
           };
           while ((data[pp].st<data[pp-1].st) && (data[pp].ta>data[pp-1].ta))
           {
                 t++; data[pp-1]=data[pp]; pp--;
           }
     };
     n-=2;
     return;
};

void check()
{
     int i,l;
     for (i=1; i<=pp; i++)
     {
         l=data[i].ta-data[i].st+1;
         if (l==len) rec++;
         if (l>len)
         {
                   len=l; rec=1;
         };
     };
};

int main()
{
     //freopen("a.in","r",stdin); freopen("a.out","w",stdout);
     len=0; pp=0; rec=1; wz=0; n=0;
     char s; s=getchar();
     while (!feof(stdin))
     {
           wz++;
           push(s,wz);
           s=getchar();
     };
     check();
     printf("%d %d\n",len,rec);
     return 0;
};


#include <iostream>

struct ab{int st,ta;} data[1000000];
struct cd{int v,z;} zhan[1000000];
int len,rec,pp,wz,n,t;

void push(char a, int b)
{
     t=1; zhan[++n].z=b;
     if (a=='(') zhan[n].v=0;
        else zhan[n].v=1;
     if (n==1) return;
     if (zhan[n].v==0) return;
     if (zhan[n-1].v==1) return;
     data[++pp].st=zhan[n-1].z; data[pp].ta=zhan[n].z;
     while ((t!=0) && (pp>1))
     {
           t=0;
           while (data[pp-1].ta==data[pp].st-1)
           {
                 t++; data[pp-1].ta=data[pp].ta; pp--;
           };
           while ((data[pp-1].st<data[pp].st) && (data[pp-1].ta>data[pp].ta))
           {
                 t++; pp--;
           };
           while ((data[pp].st<data[pp-1].st) && (data[pp].ta>data[pp-1].ta))
           {
                 t++; data[pp-1]=data[pp]; pp--;
           }
     };
     n-=2;
     return;
};

void check()
{
     int i,l;
     for (i=1; i<=pp; i++)
     {
         l=data[i].ta-data[i].st+1;
         if (l==len) rec++;
         if (l>len)
         {
                   len=l; rec=1;
         };
     };
};

int main()
{
     //freopen("a.in","r",stdin); freopen("a.out","w",stdout);
     len=0; pp=0; rec=1; wz=0; n=0;
     char s; s=getchar();
     while ((s=='(') || (s==')'))
     {
           wz++;
           push(s,wz);
           s=getchar();
     };
     check();
     printf("%d %d\n",len,rec);
     return 0;
};


#include <iostream>

struct ab{int st,ta;} data[1000000];
struct cd{int v,z;} zhan[1000000];
int len,rec,pp,wz,n,t;

void push(char a, int b)
{
     t=1; zhan[++n].z=b;
     if (a=='(') zhan[n].v=0;
        else zhan[n].v=1;
     if (n==1) return;
     if (zhan[n].v==0) return;
     if (zhan[n-1].v==1) return;
     data[++pp].st=zhan[n-1].z; data[pp].ta=zhan[n].z;
     while (t!=0)
     {
           t=0;
           while ((pp>1) && (data[pp-1].ta==data[pp].st-1))
           {
                 t++; data[pp-1].ta=data[pp].ta; pp--;
           };
           while ((pp>1) && ((data[pp].st<data[pp-1].st) && (data[pp].ta>data[pp-1].ta)))
           {
                 t++; data[pp-1]=data[pp]; pp--;
           }
     };
     n-=2;
     return;
};

void check()
{
     int i,l;
     for (i=1; i<=pp; i++)
     {
         l=data[i].ta-data[i].st+1;
         if (l==len) rec++;
         if (l>len)
         {
                   len=l; rec=1;
         };
     };
};

int main()
{
     //freopen("a.in","r",stdin); freopen("a.out","w",stdout);
     len=0; pp=0; rec=1; wz=0; n=0;
     char s; s=getchar();
     while ((s=='(') || (s==')'))
     {
           wz++;
           push(s,wz);
           s=getchar();
     };
     check();
     printf("%d %d\n",len,rec);
     return 0;
};


#include <iostream>

struct ab{int st,ta;} data[1000000];
struct cd{int v,z;} zhan[1000000];
int len,rec,pp,wz,n,t;

void push(char a, int b)
{
     t=1; zhan[++n].z=b;
     if (a=='(') zhan[n].v=0;
        else zhan[n].v=1;
     if (b==1) return;
     if (zhan[n].v==0) return;
     if (zhan[n-1].v==1) return;
     data[++pp].st=zhan[n-1].z; data[pp].ta=zhan[n].z;
     while ((t!=0) && (pp>1))
     {
           t=0;
           while (data[pp-1].ta==data[pp].st-1)
           {
                 t++; data[pp-1].ta=data[pp].ta; pp--;
           };
           while ((data[pp-1].st<data[pp].st) && (data[pp-1].ta>data[pp].ta))
           {
                 t++; pp--;
           };
           while ((data[pp].st<data[pp-1].st) && (data[pp].ta>data[pp-1].ta))
           {
                 t++; data[pp-1]=data[pp]; pp--;
           }
     };
     n-=2;
     return;
};

void check()
{
     int i,l;
     for (i=1; i<=pp; i++)
     {
         l=data[i].ta-data[i].st+1;
         if (l==len) rec++;
         if (l>len)
         {
                   len=l; rec=1;
         };
     };
};

int main()
{
     //freopen("a.in","r",stdin); freopen("a.out","w",stdout);
     len=0; pp=0; rec=1; wz=0; n=0;
     char s; s=getchar();
     while ((s=='(') || (s==')'))
     {
           wz++;
           push(s,wz);
           s=getchar();
     };
     check();
     printf("%d %d\n",len,rec);
     return 0;
};


#include <iostream>

struct ab{int st,ta;} data[1000000];
struct cd{int v,z;} zhan[1000000];
int len,rec,pp,wz,n;

void push(char a, int b)
{
     int t=1; zhan[++n].z=b;
     if (a=='(') zhan[n].v=0;
        else zhan[n].v=1;
     if (b==1) return;
     if (zhan[n].v==0) return;
     if (zhan[n-1].v==1) return;
     data[++pp].st=zhan[n-1].z; data[pp].ta=zhan[n].z;
     while ((t!=0) && (pp>1))
     {
           t=0;
           while (data[pp-1].ta==data[pp].st-1)
           {
                 t++; data[pp-1].ta=data[pp].ta; pp--;
           };
           while ((data[pp-1].st<data[pp].st) && (data[pp-1].ta>data[pp].ta))
           {
                 t++; pp--;
           };
           while ((data[pp].st<data[pp-1].st) && (data[pp].ta>data[pp-1].ta))
           {
                 t++; data[pp-1]=data[pp]; pp--;
           }
     };
     n-=2;
     return;
};

void check()
{
     int i,l;
     for (i=1; i<=pp; i++)
     {
         l=data[i].ta-data[i].st+1;
         if (l==len) rec++;
         if (l>len)
         {
                   len=l; rec=1;
         };
     };
};

int main()
{
     //freopen("a.in","r",stdin); freopen("a.out","w",stdout);
     len=0; pp=0; rec=1; wz=0; n=0;
     char s; s=getchar();
     while (!feof(stdin))
     {
           wz++;
           push(s,wz);
           s=getchar();
     };
     check();
     printf("%d %d\n",len,rec);
     return 0;
};


#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;

vector<int> bs;
vector<int> ans;
int cnt;

bool __pred(int a,int b)
{
    return b<a;
}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    char c;
    while(scanf("%c",&c)!=-1)
    {
        if(c=='(')
        {
            bs.push_back(cnt);
            ans.push_back(0);
        }
        else{
            if(!bs.empty())
            {
                int ptr = bs.back();
                bs.pop_back();
                int val = cnt-ptr+1;
                if(ptr>0)
                    val+=ans[ptr-1];
                ans.push_back(val);
            }else
                ans.push_back(0);
        }
        cnt++;
    }
    sort(ans.begin(),ans.end(),__pred);

    int a = ans[0];
    int acnt=0;
    for(int i=0;i<ans.size();i++)
        if(ans[i]==a)
            acnt++;
        else
            break;
    if(a==0)
        printf("0 1");
    else
        printf("%d %d",a,acnt);
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

vector<int> bs;
vector<int> ans;
int cnt;

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    char c;
    while(scanf("%c",&c)!=-1)
    {
        if(c=='(')
        {
            bs.push_back(cnt);
            ans.push_back(0);
            cnt++;
        }
        else if(c==')'){
            if(!bs.empty())
            {
                int ptr = bs.back();
                bs.pop_back();
                int val = cnt-ptr+1;
                if(ptr>0)
                    val+=ans[ptr-1];
                ans.push_back(val);
            }else
                ans.push_back(0);
            cnt++;
        }
    }
    sort(ans.begin(),ans.end());
    int a = ans[cnt-1];
    int acnt=0;
    for(int i=cnt-1;i>=0;i--)
        if(ans[i]==a)
            acnt++;
        else
            break;
    if(a==0)
        printf("0 1");
    else
        printf("%d %d",a,acnt);
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;

vector<int> bs;
vector<int> ans;
int cnt;

bool __pred(int a,int b)
{
    return b<a;
}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    char c;
    while(scanf("%c",&c)!=-1)
    {
        if(c=='(')
        {
            bs.push_back(cnt);
            ans.push_back(0);
            cnt++;
        }
        else if(c==')'){
            if(!bs.empty())
            {
                int ptr = bs.back();
                bs.pop_back();
                int val = cnt-ptr+1;
                if(ptr>0)
                    val+=ans[ptr-1];
                ans.push_back(val);
            }else
                ans.push_back(0);
            cnt++;
        }
        //cnt++;
    }
    sort(ans.begin(),ans.end(),__pred);

    int a = ans[0];
    int acnt=0;
    for(int i=0;i<ans.size();i++)
        if(ans[i]==a)
            acnt++;
        else
            break;
    if(a==0)
        printf("0 1");
    else
        printf("%d %d",a,acnt);
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;

vector<int> bs;
vector<int> ans;
int cnt;

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    char c;
    while(scanf("%c",&c)!=-1)
    {
        if(c=='(')
        {
            bs.push_back(cnt);
            ans.push_back(0);
        }
        else{
            if(!bs.empty())
            {
                int ptr = bs.back();
                bs.pop_back();
                int val = cnt-ptr+1;
                if(ptr>0)
                    val+=ans[ptr-1];
                ans.push_back(val);
            }else
                ans.push_back(0);
        }
        cnt++;
    }
    sort(ans.begin(),ans.end());
    int a = ans[cnt-1];
    int acnt=0;
    for(int i=cnt-1;i>=0;i--)
        if(ans[i]==a)
            acnt++;
        else
            break;
    if(a==0)
        printf("0 1");
    else
        printf("%d %d",a,acnt);
    return 0;
}


// CodeForces.cpp : Defines the entry point for the console application.
//

#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>

using namespace std;
const long long INF = 100000000;
const double EPS = 1e-9;

stack<int> st;
int main()
{
    string s;
	cin >> s;
	long res = 0;
	long maxn = 0;
	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
			st.push(i);
		else if (!st.empty())
		{
			maxn = max(maxn, i-(long)st.top()+1);
			st.pop();
		}
	}
	if (maxn == 0)
	{ cout << "0 1"; return 0;}

	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
			st.push(i);
		else if (!st.empty())
		{
			if (maxn == i-(long)st.top()+1)
				res++;
			st.pop();
		}

	}
	cout << maxn << ' ' << res << endl;

	return 0;
}

/*

*/


// CodeForces.cpp : Defines the entry point for the console application.
//

#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>

using namespace std;

stack<long> st;
int main()
{
	string s;
	cin >> s;
	long res = 0;
	long maxn = 0;
	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
			st.push(i);
		else if (!st.empty())
		{
			maxn = max(maxn, i-st.top());
			st.pop();
		}
	}
	if (maxn == 0)
	{ cout << "0 1"; return 0;}

	while(!st.empty())
		st.pop();

	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
			st.push(i);
		else if (!st.empty())
		{
			if (maxn == i-st.top())
				res++;
			st.pop();
		}

	}
	while (res == 0 || maxn%2==0);

	cout << maxn+1 << " " << res << endl;

	return 0;
}

/*

*/


// CodeForces.cpp : Defines the entry point for the console application.
//

#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>

using namespace std;
const long long INF = 100000000;
const double EPS = 1e-9;

stack<int> st;
int main()
{
    string s;
	cin >> s;
	long o = 0, z = 0, res = 0;
	long maxn = -1;
	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
		{
			o++;
			st.push(i);
		}
		else
		{
			if (o>0)
			{
				o--;
				maxn = max(maxn, i-(long)st.top()+1);
				st.pop();
			}
			else
				z++;
		}
	}
	if (maxn == -1)
	{ cout << "0 1"; return 0;}

	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
		{
			o++;
			st.push(i);
		}
		else
		{
			if (o>0)
			{
				o--;
				if (maxn == i-(long)st.top()+1)
					res++;
				st.pop();
			}
			else
				z++;
		}
	}
	cout << maxn << ' ' << res << endl;

	return 0;
}

/*

*/


// CodeForces.cpp : Defines the entry point for the console application.
//

#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>

using namespace std;
const long long INF = 100000000;
const double EPS = 1e-9;

stack<int> st;
int main()
{
    string s;
	cin >> s;
	long res = 0;
	long maxn = 0;
	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
			st.push(i);
		else if (!st.empty())
		{
			maxn = max(maxn, i-(long)st.top()+1);
			st.pop();
		}
	}
	if (maxn == 0)
	{ cout << "0 1"; return 0;}

	while(!st.empty())
		st.pop();

	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
			st.push(i);
		else if (!st.empty())
		{
			if (maxn == i-(long)st.top()+1)
				res++;
			st.pop();
		}

	}
	cout << maxn << ' ' << res << endl;

	return 0;
}

/*

*/


#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <cmath>
#include <cctype>

#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <list>
#include <iterator>
#include <functional>

using namespace std;

typedef long long int64;
typedef unsigned long long ull;

int64 labs(int64 a)
{
        return a<0 ? (-a) : a;
}
int64 max(int64 a, int64 b)
{
        return a>b?a:b;
}
int64 min(int64 a, int64 b)
{
        return a<b?a:b;
}
template<typename T> struct Point
{
        T x, y; Point(){} Point(T xx, T yy): x(xx), y(yy){}
};
template<typename T> bool operator <(const Point<T> &p1, const Point<T> &p2)
{
        return p1.x < p2.x || p1.x == p2.x && p1.y < p2.y;
}

#define mp make_pair
#define pb push_back
#define forn(i, n) for(int (i)=0; (i)<(n); (i)++)
#define forr(i, n) for(int (i)=(n)-1; (i)>=0; (i)--)
#define forit(i,c) for((i)=(c).begin(); (i)!=(c).end(); (i)++)
#define all(x) (x).begin(), (x).end()
#define zero(a) memset((a), 0, sizeof(a))

typedef vector<int> vint;
typedef vector<bool> vbool;
typedef vector<int64> vint64;
typedef Point<int> pint;
typedef pair<int, int> pii;

struct Node
{
	int left;
	int size;

	Node(){}
	Node(int l, int sz): left(l), size(sz){}
};

bool cmp(const Node & n1, const Node & n2)
{
	return n1.size > n2.size;
}

vector<Node> vn;
vint v;
string s;
int n;

void Func(int a, int b)
{
	if (a-1 >= 0 && b + 1 < n && s[a-1] == '(' && s[b+1] == ')')
	{
		Func(a-1, b+1);
	}
	else if (a-1 >= 0 && v[a-1] != -1)
	{
		Func(vn[v[a-1]].left, b);
	}
	else
	{
		v[b] = vn.size();
		vn.push_back(Node(a, b-a+1));
	}
}

int main()
{
	//freopen("readme.txt", "r", stdin);
	cin >> s;
	n = s.size();
	v.assign(n, -1);

	forn(i, n-1)
	{
		if (s[i] == '(' && s[i+1] == ')')
		{
			Func(i+1, i);
		}
	}

	sort(all(vn), cmp);
	if (vn.empty())
	{
		cout << "0 1\n";
		return 0;
	}

	int cnt = 0;
	forn(i, vn.size())
	{
		if (vn[i].size != vn.front().size)
		{
			break;
		}
		cnt++;
	}

	cout << vn.front().size << " " << cnt << endl;

	return 0;
}
/*
3
10 10 10
10 0 10
10 10 10

*/


// CodeForces.cpp : Defines the entry point for the console application.
//

#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>

using namespace std;
const long long INF = 100000000;
const double EPS = 1e-9;

stack<int> st;
int main()
{

   string s;
	cin >> s;
	long res = 0;
	long maxn = 0;
	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
			st.push(i);
		else if (!st.empty())
		{
			maxn = max(maxn, i-(long)st.top()+1);
			st.pop();
		}
	}
	if (maxn == 0)
	{ cout << "0 1"; return 0;}

	while(!st.empty())
		st.pop();

	for (int i=0; i<s.length(); i++)
	{
		if (s[i] == '(')
			st.push(i);
		else if (!st.empty())
		{
			if (maxn == i-(long)st.top()+1)
				res++;
			st.pop();
		}

	}
	while (res == 0 || maxn%2==1);

	cout << maxn << ' ' << res << endl;

	return 0;
}

/*

*/


#include <algorithm>
#include <iostream>
#include <sstream>
#include <complex>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <queue>
#include <cmath>
#include<stack>
#include <map>
#include <set>

using namespace std;

#define all(a)		(a).begin(),(a).end()
#define sz(a)		int((a).size())
#define FOR(i,a,b)	for(int i=a;i<b;++i)
#define REP(i,n)	FOR(i,0,n)
#define UN(v)		sort(all(v)),(v).erase(unique((v).begin(),(v).end()),(v).end())
#define CL(a)		memset(a,0,sizeof a)
#define pb			push_back
#define X			first
#define Y			second
#define MP(a,b) make_pair(a, b)
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
int N, w,h;
vector<pair<pii, int> > en;
string str;
int main(){

	int i,j,l,left=0, right=0, pre=0, mx=0, count=1;
	cin>>str;
	l = str.size();
	for(i=0; i<l; ++i)
	{
		if(str[i]=='(')
			left++;
		else
			right++;
		if(left==right)
		{
			if(left + right + pre > mx)
			{
				mx = left + right + pre;
				count = 1;
			}else if(left + right + pre == mx)
					count++;
			left = right = 0;
		}else if(left < right)
		{
			pre = 0;
			left = right = 0;
		}else
		{
			if(right * 2 > mx)
			{
				mx = right * 2;
				count = 1;
			}else if(right *2 == mx)
				      if(right!=0)
				        count++;
		}
	}
	cout<<mx<<" "<<count<<endl;
	return 0;
}


#include <algorithm>
#include <iostream>
#include <sstream>
#include <complex>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <queue>
#include <cmath>
#include<stack>
#include <map>
#include <set>

using namespace std;

#define all(a)		(a).begin(),(a).end()
#define sz(a)		int((a).size())
#define FOR(i,a,b)	for(int i=a;i<b;++i)
#define REP(i,n)	FOR(i,0,n)
#define UN(v)		sort(all(v)),(v).erase(unique((v).begin(),(v).end()),(v).end())
#define CL(a)		memset(a,0,sizeof a)
#define pb			push_back
#define X			first
#define Y			second
#define MP(a,b) make_pair(a, b)
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
int N, w,h;
vector<pair<pii, int> > en;
string str;
stack<int> st;
int main(){

	int i,j,l,left=0, right=0, pre=0, mx=0, count=1, cur=0;
	cin>>str;
	l = str.size();
    for(i=0; i<l; ++i)
	{
		if(str[i]=='(')
		{
			st.push(pre);
			pre = 0;
		}else
		{
			if(!st.empty())
			{
				cur = st.top() + pre + 2;
				st.pop();
				pre = cur;
				if(cur > mx)
				{
					mx = cur;
					count = 1;
				}else if(cur == mx)
					count++;
			}else
				pre = 0 ;
		}
	}
	cout<<mx<<" "<<count<<endl;
	return 0;
}


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

#define  ll                       long long
#define  pb                       push_back
#define  lb                       lower_bound
#define  ub                       upper_bound
#define  fr                       first
#define  sc                       second
#define  memset( a, b )           memset( a, b , sizeof(a) )
#define  PI                       3.1415926535
#define  mod                        1000000007
#define  rep( i , n )            for( i=0 ; i<n; i++ )
#define  int_max                 1000000000000000000

  int t ,d , ct  , q, ans ,l ,m , r ,n , mx, mn , i, j, k ,x , y , z , s  ;

 char ch;                  string ss = "" ,  str = "" ;

    map<ll,ll>mp   ;                   set< ll >st ;

     bool vis[200003] ;                vector< ll >v[200003];

   //int a[200003] , b[200003] ;

  int color[200002] ;
   int colfreq[200003] ;
      /*  -------------------------------Main Code------------------------------- */

void dfs(ll node){
ct++ ;
vis[node]  =1 ;

for(auto h : v[node])
   if(!vis[h]) dfs(h) ;

colfreq[color[node]]++ ;
mx = max(mx , colfreq[color[node]]) ;

}

int main(){

 //cin>>t ; while( t-- ) {

      s = k = d = l  = mx =m = mn = r= q =i=j = z= x= y =ct =ans = 0;

scanf("%d%d%d" ,&n ,&m ,&k) ;

rep(i , n) scanf("%d" , &color[i+1]) ;

rep(i , m){

scanf("%d%d" , &l , &r) ;
v[l].pb(r) ; v[r].pb(l) ;

}

for(i=1 ; i<=n;  i++){
    if(!vis[i])
{   mx = 0 ;  ct = 0;
 memset(colfreq , 0) ;
  dfs(i) ;
  s += ct - mx ;

}

}
printf("%d" ,s) ;

return 0;
}


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

#define  ll                       long long
#define  pb                       push_back
#define  lb                       lower_bound
#define  ub                       upper_bound
#define  fr                       first
#define  sc                       second
#define  memset( a, b )           memset( a, b , sizeof(a) )
#define  PI                       3.1415926535
#define  mod                        1000000007
#define  rep( i , n )            for( i=0 ; i<n; i++ )
#define  int_max                 1000000000000000000

  ll t ,d , ct  , q, ans ,l ,m , r ,n , mx, mn , i, j, k ,x , y , z , s  ;

 char ch;                  string ss = "" ,  str = "" ;

    map<ll,ll>mp   ;                   set< ll >st ;

     bool vis[200003] ;                vector< ll >v[200003];

   ll a[200003] , b[200003] ;

  ll color[200002] ;
   ll colfreq[200003] ;
      /*  -------------------------------Main Code------------------------------- */

void dfs(ll node){
ct++ ;
vis[node]  =1 ;

for(auto h : v[node])
   if(!vis[h]) dfs(h) ;

colfreq[color[node]]++ ;
mx = max(mx , colfreq[color[node]]) ;

}

int main(){

        ios_base::sync_with_stdio ( false) ,
        cin.tie(nullptr ),
        cout.tie( nullptr );

 //cin>>t ; while( t-- ) {

      s = k = d = l  = mx =m = mn = r= q =i=j = z= x= y =ct =ans = 0;

cin>>n>>m>>k ;

rep(i , n) cin>>color[i+1] ;

rep(i , m){

cin>>l>>r ;
v[l].pb(r) ; v[r].pb(l) ;

}

for(i=1 ; i<=n;  i++){
    if(!vis[i])
{   mx = 0 ;  ct = 0;
 memset(colfreq , 0) ;
  dfs(i) ;
  s += ct - mx ;

}

}
cout << s  ;

return 0;
}


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

#define  ll                       long long
#define  pb                       push_back
#define  lb                       lower_bound
#define  ub                       upper_bound
#define  fr                       first
#define  sc                       second
#define  memset( a, b )           memset( a, b , sizeof(a) )
#define  PI                       3.1415926535
#define  mod                        1000000007
#define  rep( i , n )            for( i=0 ; i<n; i++ )
#define  int_max                 1000000000000000000

  int t ,d , ct  , q, ans ,l ,m , r ,n , mx, mn , i, j, k ,x , y , z , s  ;

 char ch;                  string ss = "" ,  str = "" ;

    map<ll,ll>mp   ;                   set< ll >st ;

     bool vis[200003] ;                vector< ll >v[200003];

   //int a[200003] , b[200003] ;

  int color[200002] ;
   int colfreq[200003] ;
      /*  -------------------------------Main Code------------------------------- */

void dfs(ll node){
ct++ ;
vis[node]  =1 ;

for(auto h : v[node])
   if(!vis[h]) dfs(h) ;

colfreq[color[node]]++ ;
mx = max(mx , colfreq[color[node]]) ;

}

int main(){

        ios_base::sync_with_stdio ( false) ,
        cin.tie(nullptr ),
        cout.tie( nullptr );

 //cin>>t ; while( t-- ) {

      s = k = d = l  = mx =m = mn = r= q =i=j = z= x= y =ct =ans = 0;

cin>>n>>m>>k ;

rep(i , n) cin>>color[i+1] ;

rep(i , m){

cin>>l>>r ;
v[l].pb(r) ; v[r].pb(l) ;

}

for(i=1 ; i<=n;  i++){
    if(!vis[i])
{   mx = 0 ;  ct = 0;
 memset(colfreq , 0) ;
  dfs(i) ;
  s += ct - mx ;

}

}
cout << s  ;

return 0;
}


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

#define  ll                       long long
#define  pb                       push_back
#define  lb                       lower_bound
#define  ub                       upper_bound
#define  fr                       first
#define  sc                       second
#define  memset( a, b )           memset( a, b , sizeof(a) )
#define  PI                       3.1415926535
#define  mod                        1000000007
#define  rep( i , n )            for( i=0 ; i<n; i++ )
#define  int_max                 1000000000000000000

  int t ,d , ct  , q, ans ,l ,m , r ,n , mx, mn , i, j, k ,x , y , z , s  ;

 char ch;                  string ss = "" ,  str = "" ;

    map<int,int>mp   ;                   set< ll >st ;

     bool vis[200003] ;                vector< ll >v[200003];

   //int a[200003] , b[200003] ;

  int color[200002] ;
      /*  -------------------------------Main Code------------------------------- */

void dfs(ll node){
ct++ ;
vis[node]  =1 ;

for(auto h : v[node])
   if(!vis[h]) dfs(h) ;

mp[color[node]]++ ;
mx = max(mx , mp[color[node]]) ;

}

int main(){

 //cin>>t ; while( t-- ) {

      s = k = d = l  = mx =m = mn = r= q =i=j = z= x= y =ct =ans = 0;

scanf("%d%d%d" ,&n ,&m ,&k) ;

rep(i , n) scanf("%d" , &color[i+1]) ;

rep(i , m){

scanf("%d%d" , &l , &r) ;
v[l].pb(r) ; v[r].pb(l) ;

}

for(i=1 ; i<=n;  i++){
    if(!vis[i])
{   mx = 0 ;  ct = 0;
     mp.clear() ;
    dfs(i) ;
  s += ct - mx ;

}

}
printf("%d" ,s) ;

return 0;
}


//jenil mehta
#include <bits/stdc++.h>
#define ll long long int
using namespace std;
vector<ll> c(200005);
vector<ll> visited(200005);
vector<vector<ll> > a(200005);
ll p,cnt;
map <ll,ll> mp;
void dfs(ll node)
{
    cnt++;
    visited[node]=1;
    mp[c[node]]++;
    p=max(p,mp[c[node]]);

    for(auto i:a[node])
    {
        if(!visited[i])
        {
            dfs(i);
        }
    }
}
int main()
{
    ll n;
    ll m,k;
    cin>>n>>m>>k;
    ll i,j;
    for(i=1;i<=n;i++)
    {
        cin>>c[i];
    }
    ll x,y;
    ll ans=0;
    for(i=0;i<m;i++)
    {
        cin>>x>>y;
        a[x].push_back(y);
        a[y].push_back(x);
    }
    for(i=1;i<=n;i++)
    {
        if(!visited[i])
        {
            mp.clear();
            dfs(i);
            ans+=(cnt-p);
        }
    }
    cout<<ans<<endl;
}


//jenil mehta
#include <bits/stdc++.h>
#define ll long long int
using namespace std;
vector<ll> c(200005);
vector<ll> visited(200005);
vector<vector<ll> > a(200005);
ll p,cnt;
map <ll,ll> mp;
void dfs(ll node)
{
    cnt++;
    visited[node]=1;
    mp[c[node]]++;
    p=max(p,mp[c[node]]);

    for(auto i:a[node])
    {
        if(!visited[i])
        {
            dfs(i);
        }
    }
}
int main()
{
    ll n;
    ll m,k;
    cin>>n>>m>>k;
    ll i,j;
    for(i=1;i<=n;i++)
    {
        cin>>c[i];
    }
    ll x,y;
    ll ans=0;
    for(i=0;i<m;i++)
    {
        cin>>x>>y;
        a[x].push_back(y);
        a[y].push_back(x);
    }
    for(i=0;i<n;i++)
    {
        if(!visited[i])
        {
            dfs(i);
            ans+=(cnt-p);
        }
    }
    cout<<ans<<endl;
}


//jenil mehta
#include <bits/stdc++.h>
#define ll long long int
using namespace std;
vector <ll> a[200001];
int main()
{
    ll n;
    ll m,k;
    cin>>n>>m>>k;
    ll c[n+1];
    ll i,j;
    for(i=1;i<=n;i++)
    {
        cin>>c[i];
    }
    ll x,y;
    ll ans=0;
    for(i=0;i<m;i++)
    {
        cin>>x>>y;
        if(c[x]!=c[y])
        {
            ans++;
        }
    }
    cout<<ans<<endl;
}


//jenil mehta
#include <bits/stdc++.h>
#define ll long long int
using namespace std;
vector<ll> c(200005);
vector<ll> visited(200005);
vector<vector<ll> > a(200005);
ll p,cnt;
map <ll,ll> mp;
void dfs(ll node)
{
    cnt++;
    visited[node]=1;
    mp[c[node]]++;
    p=max(p,mp[c[node]]);

    for(auto i:a[node])
    {
        if(!visited[i])
        {
            dfs(i);
        }
    }
}
int main()
{
    ll n;
    ll m,k;
    cin>>n>>m>>k;
    ll i,j;
    for(i=0;i<n;i++)
    {
        cin>>c[i];
        c[i]--;
    }
    ll x,y;
    ll ans=0;
    for(i=0;i<m;i++)
    {
        cin>>x>>y;
        x--;
        y--;
        a[x].push_back(y);
        a[y].push_back(x);
    }
    for(i=0;i<n;i++)
    {
        if(!visited[i])
        {
            p=0;
	        cnt=0;
            mp.clear();
            dfs(i);
            ans+=(cnt-p);
        }
    }
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
/*{{ x | (1 << k) sets the kth bit of x to one
x & ~(1 << k) sets the kth bit of x to zero
x ^ (1 << k) inverts the kth bit of x.
x & (x−1) sets the last one bit of x to zero
x & −x sets all the one bits to zero, except for the last one bit.
x | (x−1) inverts all the bits after the last one bit.}} SOME BIT MANIPULATION*/
//__builtin_clz(x): the number of zeros at the beginning of the number
//__builtin_ctz(x): the number of zeros at the end of the number
//__builtin_popcount(x): the number of ones in the number
//__builtin_parity(x): the parity (even or odd) of the number of ones
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<ll,ll> pi;
#define INF 1e18
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define G(a,b) get<a>(b)
#define REP(i,a,b) for(ll i = a; i<=b; i++)
#define REPI(i, a, n)  for(int i = a; i >= (n); --i)
#define maxe(v) *max_element(v.begin(), v.end())
#define mine(v) *min_element(v.begin(), v.end())
#define endl "\n"
//LAZY SEGMENT TREE START
void build(ll v,ll tl,ll tr,ll st[],ll lz[],bool f[],ll a[])
{
    if(tl==tr)
    {
        st[v]=a[tl];
        lz[v]=0LL;
        f[v]=false;
        return;
    }
    build((v<<1),tl,((tl+tr)>>1),st,lz,f,a);
    build((v<<1)|1,((tl+tr)>>1)+1,tr,st,lz,f,a);
    //operation
    st[v]=st[(v<<1)]+st[(v<<1)|1];
    lz[v]=0LL;
    f[v]=false;
    return;
}

void push(ll v,ll tl,ll tr,ll st[],ll lz[],bool f[])
{
    if(f[v])
    {
        //operation
        st[(v<<1)]=lz[(v<<1)]=st[(v<<1)|1]=lz[(v<<1)|1]=0LL;
        f[(v<<1)]=f[(v<<1)|1]=true;
        f[v]=false;
    }
    //operation
    st[(v<<1)]+=lz[v]*(((tl+tr)>>1)-tl+1);
    //operation
    lz[(v<<1)]+=lz[v];
    //operation
    st[(v<<1)|1]+=lz[v]*(tr-((tl+tr)>>1));
    //operation
    lz[(v<<1)|1]+=lz[v];
    lz[v]=0LL;
    return;
}

void update(ll v,ll tl,ll tr,ll l,ll r,ll val,bool set,ll st[],ll lz[],bool f[])
{
    if(l>r)
    {
        return;
    }
    if(l==tl&&tr==r)
    {
        if(set)
        {
            //operation
            st[v]=lz[v]=0LL;
            f[v]=true;
        }
        //operation
        st[v]+=val*(tr-tl+1);
        //operation
        lz[v]+=val;
        return;
    }
    push(v,tl,tr,st,lz,f);
    update((v<<1),tl,((tl+tr)>>1),l,min(r,((tl+tr)>>1)),val,set,st,lz,f);
    update((v<<1)|1,((tl+tr)>>1)+1,tr,max(l,((tl+tr)>>1)+1),r,val,set,st,lz,f);
    //operation
    st[v]=st[(v<<1)]+st[(v<<1)|1];
    return;
}

ll query(ll v,ll tl,ll tr,ll l,ll r,ll st[],ll lz[],bool f[])
{
    if(l>r)
    {
        return 0LL;
    }
    if(l==tl&&tr==r)
    {
        return st[v];
    }
    push(v,tl,tr,st,lz,f);
    //operation
    return query((v<<1),tl,((tl+tr)>>1),l,min(r,((tl+tr)>>1)),st,lz,f)+query((v<<1)|1,((tl+tr)>>1)+1,tr,max(l,((tl+tr)>>1)+1),r,st,lz,f);
}
//LAZY SEGMENT TREE END

// SEGMENT TREE START
 void build(int v,int tl,int tr,int a[],long long st[]) // building the segment tree
{
    if(tl==tr) // when reaching the leaf node giving segment tree value the given array value
    {
        st[v]=a[tl];
        return;
    }
    int tm=((tl+tr)/2); // distributing the value of present node in two successor nodes
    build(2*v,tl,tm,a,st); // left end to middle
    build(2*v+1,tm+1,tr,a,st); // middle to right end
    st[v]=st[v*2]+st[v*2+1]; // giving value to the parent of the two succesor nodes
    return;
}

void update(int v,int tl,int tr,int pos,int val,long long st[])
{
    if(tl==tr&&tl==pos) // updating the value if the reached leaf node is equal to pos
    {
        st[v]=val;
        return;
    }
    if(tl>pos||tr<pos)
    {
        return; // avoiding segmentation fault
    }
    int tm=((tl+tr)/2);// distributing the value of present node in two successor nodes
    update(2*v,tl,tm,pos,val,st);// left end to middle
    update(2*v+1,tm+1,tr,pos,val,st);// middle to right end
    st[v]=st[v*2]+st[v*2+1]; // giving value to the parent of the two succesor nodes
    return;
}

long long query(int v,int tl,int tr,int l,int r,long long st[])
{
    if(tl==l&&tr==r) // returning the value of the corresponding node if given range equals the range of node
    {
        return st[v];
    }
    if(l>r) // avoiding excess traversal which is not required
    {
        return 0LL;
    }
    int tm=((tl+tr)/2);
    return query(v*2,tl,tm,l,std::min(tm,r),st)+query(v*2+1,tm+1,tr,std::max(tm+1,l),r,st); // (max):- cuz cant be less than left extremity, (min):- cuz cant be greater than righ extremity
}

//SEGMENT TREE END

// DISJOINT SET UNION START
ll fn(ll x,ll rn[]) // finding the component
{
    if(x==rn[x]) // Top of its component
        return x;
    else //making parent node of each node of the component the highest node
        return rn[x]=fn(rn[x],rn);
}

bool un(ll x,ll y,ll rn[],ll sz[])// union of components
{
    x=fn(x,rn);
    y=fn(y,rn);
    if(x==y)// if connected already
        return false;
    if(sz[x]<sz[y])// otherwise connectiing light to heavy by swapping
        swap(x,y);
    sz[x]+=sz[y];
    rn[y]=x;// making parent node;
    return true;
}

//DISJOINT SET UNION END
ll power(ll k)
{
    ll temp=1;
    REP(i,0,k-1)
    {
        temp=temp*2;
    }
    return temp;
}
bool compare(const pair<ll,ll>&a, const pair<ll,ll>&b)
{
    return a.S<b.S;
}
pair<int,int> mostFrequent(ll arr[], ll n)
{
    unordered_map<ll, ll> hash;
    for (ll i = 0; i < n; i++)
        hash[arr[i]]++;

    ll max_count = 0, res = -1;
    for (auto i : hash) {
        if (max_count < i.second) {
            res = i.first;
            max_count = i.second;
        }
    }
    pair<ll,ll> temp;
    temp.F=res;
    temp.S=max_count;
    return temp;
}
string findSum(string str1, string str2)
{
    // Before proceeding further, make sure length
    // of str2 is larger.
    if (str1.length() > str2.length())
        swap(str1, str2);

    // Take an empty string for storing result
    string str = "";

    // Calculate length of both string
    int n1 = str1.length(), n2 = str2.length();

    // Reverse both of strings
    reverse(str1.begin(), str1.end());
    reverse(str2.begin(), str2.end());

    int carry = 0;
    for (int i=0; i<n1; i++)
    {
        // Do school mathematics, compute sum of
        // current digits and carry
        int sum = ((str1[i]-'0')+(str2[i]-'0')+carry);
        str.push_back(sum%10 + '0');

        // Calculate carry for next step
        carry = sum/10;
    }

    // Add remaining digits of larger number
    for (int i=n1; i<n2; i++)
    {
        int sum = ((str2[i]-'0')+carry);
        str.push_back(sum%10 + '0');
        carry = sum/10;
    }

    // Add remaining carry
    if (carry)
        str.push_back(carry+'0');

    // reverse resultant string
    reverse(str.begin(), str.end());

    return str;
}
ll div(ll n)
{
    if (n % 2 == 0)
        return 2;
    for (ll i = 3; i * i <= n; i += 2) {
        if (n % i == 0)
            return i;
    }
    return n;
}
ll gcd(ll a, ll b){if(!b)return a;return gcd(b, a % b);}
ll lcm(ll a , ll b){return (a*b)/gcd(a,b);}
bool sec(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.F > b.F);
}
bool sec1(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.second > b.second);
}
ll msum(ll a[], ll size)
{
   ll max_so_far = a[0];
   ll curr_max = a[0];

   for (ll i = 1; i < size; i++)
   {
        curr_max = max(a[i], curr_max+a[i]);
        max_so_far = max(max_so_far, curr_max);
   }
   return max_so_far;
}
vector<ll> v[200010];
vector<bool> vis(200010,0);
map<ll,ll> st;
ll um[200010];
void dfs(ll t)
{
    vis[t]=1;
    st[um[t]]++;
    for(auto u:v[t])
    {
        if(vis[u]==0)
        {
            dfs(u);
        }
    }
}
int main()
{
    ios_base::sync_with_stdio(0);
	cin.tie(0);
    cout.tie(0);

    ll n,m,k;
    cin>>n>>m>>k;
    REP(i,1,n)
    {
        ll c;
        cin>>c;
        um[i]=c;
    }
    REP(i,0,m-1)
    {
        ll x,y;
        cin>>x>>y;
        v[x].PB(y);
        v[y].PB(x);
    }
    ll ans=0;
    REP(i,1,n)
    {
        if(vis[i]==0)
        {
            st.clear();
            dfs(i);
            ll mx=0;
            for(auto it:st)
                mx=max(mx,it.S);
            ans=ans+(((ll)st.size())-mx);
        }
    }
    cout<<ans;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
/*{{ x | (1 << k) sets the kth bit of x to one
x & ~(1 << k) sets the kth bit of x to zero
x ^ (1 << k) inverts the kth bit of x.
x & (x−1) sets the last one bit of x to zero
x & −x sets all the one bits to zero, except for the last one bit.
x | (x−1) inverts all the bits after the last one bit.}} SOME BIT MANIPULATION*/
//__builtin_clz(x): the number of zeros at the beginning of the number
//__builtin_ctz(x): the number of zeros at the end of the number
//__builtin_popcount(x): the number of ones in the number
//__builtin_parity(x): the parity (even or odd) of the number of ones
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<ll,ll> pi;
#define INF 1e18
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define G(a,b) get<a>(b)
#define REP(i,a,b) for(ll i = a; i<=b; i++)
#define REPI(i, a, n)  for(int i = a; i >= (n); --i)
#define maxe(v) *max_element(v.begin(), v.end())
#define mine(v) *min_element(v.begin(), v.end())
#define endl "\n"
//LAZY SEGMENT TREE START
void build(ll v,ll tl,ll tr,ll st[],ll lz[],bool f[],ll a[])
{
    if(tl==tr)
    {
        st[v]=a[tl];
        lz[v]=0LL;
        f[v]=false;
        return;
    }
    build((v<<1),tl,((tl+tr)>>1),st,lz,f,a);
    build((v<<1)|1,((tl+tr)>>1)+1,tr,st,lz,f,a);
    //operation
    st[v]=st[(v<<1)]+st[(v<<1)|1];
    lz[v]=0LL;
    f[v]=false;
    return;
}

void push(ll v,ll tl,ll tr,ll st[],ll lz[],bool f[])
{
    if(f[v])
    {
        //operation
        st[(v<<1)]=lz[(v<<1)]=st[(v<<1)|1]=lz[(v<<1)|1]=0LL;
        f[(v<<1)]=f[(v<<1)|1]=true;
        f[v]=false;
    }
    //operation
    st[(v<<1)]+=lz[v]*(((tl+tr)>>1)-tl+1);
    //operation
    lz[(v<<1)]+=lz[v];
    //operation
    st[(v<<1)|1]+=lz[v]*(tr-((tl+tr)>>1));
    //operation
    lz[(v<<1)|1]+=lz[v];
    lz[v]=0LL;
    return;
}

void update(ll v,ll tl,ll tr,ll l,ll r,ll val,bool set,ll st[],ll lz[],bool f[])
{
    if(l>r)
    {
        return;
    }
    if(l==tl&&tr==r)
    {
        if(set)
        {
            //operation
            st[v]=lz[v]=0LL;
            f[v]=true;
        }
        //operation
        st[v]+=val*(tr-tl+1);
        //operation
        lz[v]+=val;
        return;
    }
    push(v,tl,tr,st,lz,f);
    update((v<<1),tl,((tl+tr)>>1),l,min(r,((tl+tr)>>1)),val,set,st,lz,f);
    update((v<<1)|1,((tl+tr)>>1)+1,tr,max(l,((tl+tr)>>1)+1),r,val,set,st,lz,f);
    //operation
    st[v]=st[(v<<1)]+st[(v<<1)|1];
    return;
}

ll query(ll v,ll tl,ll tr,ll l,ll r,ll st[],ll lz[],bool f[])
{
    if(l>r)
    {
        return 0LL;
    }
    if(l==tl&&tr==r)
    {
        return st[v];
    }
    push(v,tl,tr,st,lz,f);
    //operation
    return query((v<<1),tl,((tl+tr)>>1),l,min(r,((tl+tr)>>1)),st,lz,f)+query((v<<1)|1,((tl+tr)>>1)+1,tr,max(l,((tl+tr)>>1)+1),r,st,lz,f);
}
//LAZY SEGMENT TREE END

// SEGMENT TREE START
 void build(int v,int tl,int tr,int a[],long long st[]) // building the segment tree
{
    if(tl==tr) // when reaching the leaf node giving segment tree value the given array value
    {
        st[v]=a[tl];
        return;
    }
    int tm=((tl+tr)/2); // distributing the value of present node in two successor nodes
    build(2*v,tl,tm,a,st); // left end to middle
    build(2*v+1,tm+1,tr,a,st); // middle to right end
    st[v]=st[v*2]+st[v*2+1]; // giving value to the parent of the two succesor nodes
    return;
}

void update(int v,int tl,int tr,int pos,int val,long long st[])
{
    if(tl==tr&&tl==pos) // updating the value if the reached leaf node is equal to pos
    {
        st[v]=val;
        return;
    }
    if(tl>pos||tr<pos)
    {
        return; // avoiding segmentation fault
    }
    int tm=((tl+tr)/2);// distributing the value of present node in two successor nodes
    update(2*v,tl,tm,pos,val,st);// left end to middle
    update(2*v+1,tm+1,tr,pos,val,st);// middle to right end
    st[v]=st[v*2]+st[v*2+1]; // giving value to the parent of the two succesor nodes
    return;
}

long long query(int v,int tl,int tr,int l,int r,long long st[])
{
    if(tl==l&&tr==r) // returning the value of the corresponding node if given range equals the range of node
    {
        return st[v];
    }
    if(l>r) // avoiding excess traversal which is not required
    {
        return 0LL;
    }
    int tm=((tl+tr)/2);
    return query(v*2,tl,tm,l,std::min(tm,r),st)+query(v*2+1,tm+1,tr,std::max(tm+1,l),r,st); // (max):- cuz cant be less than left extremity, (min):- cuz cant be greater than righ extremity
}

//SEGMENT TREE END

// DISJOINT SET UNION START
ll fn(ll x,ll rn[]) // finding the component
{
    if(x==rn[x]) // Top of its component
        return x;
    else //making parent node of each node of the component the highest node
        return rn[x]=fn(rn[x],rn);
}

bool un(ll x,ll y,ll rn[],ll sz[])// union of components
{
    x=fn(x,rn);
    y=fn(y,rn);
    if(x==y)// if connected already
        return false;
    if(sz[x]<sz[y])// otherwise connectiing light to heavy by swapping
        swap(x,y);
    sz[x]+=sz[y];
    rn[y]=x;// making parent node;
    return true;
}

//DISJOINT SET UNION END
ll power(ll k)
{
    ll temp=1;
    REP(i,0,k-1)
    {
        temp=temp*2;
    }
    return temp;
}
bool compare(const pair<ll,ll>&a, const pair<ll,ll>&b)
{
    return a.S<b.S;
}
pair<int,int> mostFrequent(ll arr[], ll n)
{
    unordered_map<ll, ll> hash;
    for (ll i = 0; i < n; i++)
        hash[arr[i]]++;

    ll max_count = 0, res = -1;
    for (auto i : hash) {
        if (max_count < i.second) {
            res = i.first;
            max_count = i.second;
        }
    }
    pair<ll,ll> temp;
    temp.F=res;
    temp.S=max_count;
    return temp;
}
string findSum(string str1, string str2)
{
    // Before proceeding further, make sure length
    // of str2 is larger.
    if (str1.length() > str2.length())
        swap(str1, str2);

    // Take an empty string for storing result
    string str = "";

    // Calculate length of both string
    int n1 = str1.length(), n2 = str2.length();

    // Reverse both of strings
    reverse(str1.begin(), str1.end());
    reverse(str2.begin(), str2.end());

    int carry = 0;
    for (int i=0; i<n1; i++)
    {
        // Do school mathematics, compute sum of
        // current digits and carry
        int sum = ((str1[i]-'0')+(str2[i]-'0')+carry);
        str.push_back(sum%10 + '0');

        // Calculate carry for next step
        carry = sum/10;
    }

    // Add remaining digits of larger number
    for (int i=n1; i<n2; i++)
    {
        int sum = ((str2[i]-'0')+carry);
        str.push_back(sum%10 + '0');
        carry = sum/10;
    }

    // Add remaining carry
    if (carry)
        str.push_back(carry+'0');

    // reverse resultant string
    reverse(str.begin(), str.end());

    return str;
}
ll div(ll n)
{
    if (n % 2 == 0)
        return 2;
    for (ll i = 3; i * i <= n; i += 2) {
        if (n % i == 0)
            return i;
    }
    return n;
}
ll gcd(ll a, ll b){if(!b)return a;return gcd(b, a % b);}
ll lcm(ll a , ll b){return (a*b)/gcd(a,b);}
bool sec(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.F > b.F);
}
bool sec1(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.second > b.second);
}
ll msum(ll a[], ll size)
{
   ll max_so_far = a[0];
   ll curr_max = a[0];

   for (ll i = 1; i < size; i++)
   {
        curr_max = max(a[i], curr_max+a[i]);
        max_so_far = max(max_so_far, curr_max);
   }
   return max_so_far;
}
vector<ll> v[200010];
vector<bool> vis(200010,0);
map<ll,ll> st;
ll um[200010];
void dfs(ll t)
{
    vis[t]=1;
    st[um[t]]++;
    for(auto u:v[t])
    {
        if(vis[u]==0)
        {
            dfs(u);
        }
    }
}
int main()
{
    ios_base::sync_with_stdio(0);
	cin.tie(0);
    cout.tie(0);

    ll n,m,k;
    cin>>n>>m>>k;
    REP(i,1,n)
    {
        ll c;
        cin>>c;
        um[i]=c;
    }
    REP(i,0,m-1)
    {
        ll x,y;
        cin>>x>>y;
        v[x].PB(y);
        v[y].PB(x);
    }
    ll ans=0;
    REP(i,1,n)
    {
        if(vis[i]==0)
        {
            st.clear();
            dfs(i);
            ll mx=0;
            for(auto it:st)
                mx=max(mx,it.S);
            ll sm=0;
            for(auto it:st)
                sm+=it.S;
            ans+=(sm-mx);
        }
    }
    cout<<ans;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
/*{{ x | (1 << k) sets the kth bit of x to one
x & ~(1 << k) sets the kth bit of x to zero
x ^ (1 << k) inverts the kth bit of x.
x & (x−1) sets the last one bit of x to zero
x & −x sets all the one bits to zero, except for the last one bit.
x | (x−1) inverts all the bits after the last one bit.}} SOME BIT MANIPULATION*/
//__builtin_clz(x): the number of zeros at the beginning of the number
//__builtin_ctz(x): the number of zeros at the end of the number
//__builtin_popcount(x): the number of ones in the number
//__builtin_parity(x): the parity (even or odd) of the number of ones
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<ll,ll> pi;
#define INF 1e18
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define G(a,b) get<a>(b)
#define REP(i,a,b) for(ll i = a; i<=b; i++)
#define REPI(i, a, n)  for(int i = a; i >= (n); --i)
#define maxe(v) *max_element(v.begin(), v.end())
#define mine(v) *min_element(v.begin(), v.end())
#define endl "\n"
//LAZY SEGMENT TREE START
void build(ll v,ll tl,ll tr,ll st[],ll lz[],bool f[],ll a[])
{
    if(tl==tr)
    {
        st[v]=a[tl];
        lz[v]=0LL;
        f[v]=false;
        return;
    }
    build((v<<1),tl,((tl+tr)>>1),st,lz,f,a);
    build((v<<1)|1,((tl+tr)>>1)+1,tr,st,lz,f,a);
    //operation
    st[v]=st[(v<<1)]+st[(v<<1)|1];
    lz[v]=0LL;
    f[v]=false;
    return;
}

void push(ll v,ll tl,ll tr,ll st[],ll lz[],bool f[])
{
    if(f[v])
    {
        //operation
        st[(v<<1)]=lz[(v<<1)]=st[(v<<1)|1]=lz[(v<<1)|1]=0LL;
        f[(v<<1)]=f[(v<<1)|1]=true;
        f[v]=false;
    }
    //operation
    st[(v<<1)]+=lz[v]*(((tl+tr)>>1)-tl+1);
    //operation
    lz[(v<<1)]+=lz[v];
    //operation
    st[(v<<1)|1]+=lz[v]*(tr-((tl+tr)>>1));
    //operation
    lz[(v<<1)|1]+=lz[v];
    lz[v]=0LL;
    return;
}

void update(ll v,ll tl,ll tr,ll l,ll r,ll val,bool set,ll st[],ll lz[],bool f[])
{
    if(l>r)
    {
        return;
    }
    if(l==tl&&tr==r)
    {
        if(set)
        {
            //operation
            st[v]=lz[v]=0LL;
            f[v]=true;
        }
        //operation
        st[v]+=val*(tr-tl+1);
        //operation
        lz[v]+=val;
        return;
    }
    push(v,tl,tr,st,lz,f);
    update((v<<1),tl,((tl+tr)>>1),l,min(r,((tl+tr)>>1)),val,set,st,lz,f);
    update((v<<1)|1,((tl+tr)>>1)+1,tr,max(l,((tl+tr)>>1)+1),r,val,set,st,lz,f);
    //operation
    st[v]=st[(v<<1)]+st[(v<<1)|1];
    return;
}

ll query(ll v,ll tl,ll tr,ll l,ll r,ll st[],ll lz[],bool f[])
{
    if(l>r)
    {
        return 0LL;
    }
    if(l==tl&&tr==r)
    {
        return st[v];
    }
    push(v,tl,tr,st,lz,f);
    //operation
    return query((v<<1),tl,((tl+tr)>>1),l,min(r,((tl+tr)>>1)),st,lz,f)+query((v<<1)|1,((tl+tr)>>1)+1,tr,max(l,((tl+tr)>>1)+1),r,st,lz,f);
}
//LAZY SEGMENT TREE END

// SEGMENT TREE START
 void build(int v,int tl,int tr,int a[],long long st[]) // building the segment tree
{
    if(tl==tr) // when reaching the leaf node giving segment tree value the given array value
    {
        st[v]=a[tl];
        return;
    }
    int tm=((tl+tr)/2); // distributing the value of present node in two successor nodes
    build(2*v,tl,tm,a,st); // left end to middle
    build(2*v+1,tm+1,tr,a,st); // middle to right end
    st[v]=st[v*2]+st[v*2+1]; // giving value to the parent of the two succesor nodes
    return;
}

void update(int v,int tl,int tr,int pos,int val,long long st[])
{
    if(tl==tr&&tl==pos) // updating the value if the reached leaf node is equal to pos
    {
        st[v]=val;
        return;
    }
    if(tl>pos||tr<pos)
    {
        return; // avoiding segmentation fault
    }
    int tm=((tl+tr)/2);// distributing the value of present node in two successor nodes
    update(2*v,tl,tm,pos,val,st);// left end to middle
    update(2*v+1,tm+1,tr,pos,val,st);// middle to right end
    st[v]=st[v*2]+st[v*2+1]; // giving value to the parent of the two succesor nodes
    return;
}

long long query(int v,int tl,int tr,int l,int r,long long st[])
{
    if(tl==l&&tr==r) // returning the value of the corresponding node if given range equals the range of node
    {
        return st[v];
    }
    if(l>r) // avoiding excess traversal which is not required
    {
        return 0LL;
    }
    int tm=((tl+tr)/2);
    return query(v*2,tl,tm,l,std::min(tm,r),st)+query(v*2+1,tm+1,tr,std::max(tm+1,l),r,st); // (max):- cuz cant be less than left extremity, (min):- cuz cant be greater than righ extremity
}

//SEGMENT TREE END

// DISJOINT SET UNION START
ll fn(ll x,ll rn[]) // finding the component
{
    if(x==rn[x]) // Top of its component
        return x;
    else //making parent node of each node of the component the highest node
        return rn[x]=fn(rn[x],rn);
}

bool un(ll x,ll y,ll rn[],ll sz[])// union of components
{
    x=fn(x,rn);
    y=fn(y,rn);
    if(x==y)// if connected already
        return false;
    if(sz[x]<sz[y])// otherwise connectiing light to heavy by swapping
        swap(x,y);
    sz[x]+=sz[y];
    rn[y]=x;// making parent node;
    return true;
}

//DISJOINT SET UNION END
ll power(ll k)
{
    ll temp=1;
    REP(i,0,k-1)
    {
        temp=temp*2;
    }
    return temp;
}
bool compare(const pair<ll,ll>&a, const pair<ll,ll>&b)
{
    return a.S<b.S;
}
pair<int,int> mostFrequent(ll arr[], ll n)
{
    unordered_map<ll, ll> hash;
    for (ll i = 0; i < n; i++)
        hash[arr[i]]++;

    ll max_count = 0, res = -1;
    for (auto i : hash) {
        if (max_count < i.second) {
            res = i.first;
            max_count = i.second;
        }
    }
    pair<ll,ll> temp;
    temp.F=res;
    temp.S=max_count;
    return temp;
}
string findSum(string str1, string str2)
{
    // Before proceeding further, make sure length
    // of str2 is larger.
    if (str1.length() > str2.length())
        swap(str1, str2);

    // Take an empty string for storing result
    string str = "";

    // Calculate length of both string
    int n1 = str1.length(), n2 = str2.length();

    // Reverse both of strings
    reverse(str1.begin(), str1.end());
    reverse(str2.begin(), str2.end());

    int carry = 0;
    for (int i=0; i<n1; i++)
    {
        // Do school mathematics, compute sum of
        // current digits and carry
        int sum = ((str1[i]-'0')+(str2[i]-'0')+carry);
        str.push_back(sum%10 + '0');

        // Calculate carry for next step
        carry = sum/10;
    }

    // Add remaining digits of larger number
    for (int i=n1; i<n2; i++)
    {
        int sum = ((str2[i]-'0')+carry);
        str.push_back(sum%10 + '0');
        carry = sum/10;
    }

    // Add remaining carry
    if (carry)
        str.push_back(carry+'0');

    // reverse resultant string
    reverse(str.begin(), str.end());

    return str;
}
ll div(ll n)
{
    if (n % 2 == 0)
        return 2;
    for (ll i = 3; i * i <= n; i += 2) {
        if (n % i == 0)
            return i;
    }
    return n;
}
ll gcd(ll a, ll b){if(!b)return a;return gcd(b, a % b);}
ll lcm(ll a , ll b){return (a*b)/gcd(a,b);}
bool sec(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.F > b.F);
}
bool sec1(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.second > b.second);
}
ll msum(ll a[], ll size)
{
   ll max_so_far = a[0];
   ll curr_max = a[0];

   for (ll i = 1; i < size; i++)
   {
        curr_max = max(a[i], curr_max+a[i]);
        max_so_far = max(max_so_far, curr_max);
   }
   return max_so_far;
}
vector<ll> v[200001];
vector<bool> vis(200001,0);
set<ll> st;
void dfs(ll t,map<ll,ll> &um)
{
    vis[t]=1;
    st.insert(um[t]);
    for(auto u:v[t])
    {
        if(vis[u]==0)
        {
            dfs(u,um);
        }
    }
}
int main()
{
    ios_base::sync_with_stdio(0);
	cin.tie(0);
    cout.tie(0);

    ll n,m,k;
    cin>>n>>m>>k;
    if(m==0)
    {
        cout<<0;
        return 0;
    }
    map<ll,ll> um;
    REP(i,1,n)
    {
        ll c;
        cin>>c;
        um[i]=c;
    }
    REP(i,0,m-1)
    {
        ll x,y;
        cin>>x>>y;
        v[x].PB(y);
        v[y].PB(x);
    }
    ll ans=0;
    REP(i,1,n)
    {
        if(vis[i]==0)
        {
            dfs(i,um);
            ans=ans+(st.size()-1);
            st.clear();
        }
    }
    cout<<ans;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
/*{{ x | (1 << k) sets the kth bit of x to one
x & ~(1 << k) sets the kth bit of x to zero
x ^ (1 << k) inverts the kth bit of x.
x & (x−1) sets the last one bit of x to zero
x & −x sets all the one bits to zero, except for the last one bit.
x | (x−1) inverts all the bits after the last one bit.}} SOME BIT MANIPULATION*/
//__builtin_clz(x): the number of zeros at the beginning of the number
//__builtin_ctz(x): the number of zeros at the end of the number
//__builtin_popcount(x): the number of ones in the number
//__builtin_parity(x): the parity (even or odd) of the number of ones
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<ll,ll> pi;
#define INF 1e18
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define G(a,b) get<a>(b)
#define REP(i,a,b) for(ll i = a; i<=b; i++)
#define REPI(i, a, n)  for(int i = a; i >= (n); --i)
#define maxe(v) *max_element(v.begin(), v.end())
#define mine(v) *min_element(v.begin(), v.end())
#define endl "\n"
//LAZY SEGMENT TREE START
void build(ll v,ll tl,ll tr,ll st[],ll lz[],bool f[],ll a[])
{
    if(tl==tr)
    {
        st[v]=a[tl];
        lz[v]=0LL;
        f[v]=false;
        return;
    }
    build((v<<1),tl,((tl+tr)>>1),st,lz,f,a);
    build((v<<1)|1,((tl+tr)>>1)+1,tr,st,lz,f,a);
    //operation
    st[v]=st[(v<<1)]+st[(v<<1)|1];
    lz[v]=0LL;
    f[v]=false;
    return;
}

void push(ll v,ll tl,ll tr,ll st[],ll lz[],bool f[])
{
    if(f[v])
    {
        //operation
        st[(v<<1)]=lz[(v<<1)]=st[(v<<1)|1]=lz[(v<<1)|1]=0LL;
        f[(v<<1)]=f[(v<<1)|1]=true;
        f[v]=false;
    }
    //operation
    st[(v<<1)]+=lz[v]*(((tl+tr)>>1)-tl+1);
    //operation
    lz[(v<<1)]+=lz[v];
    //operation
    st[(v<<1)|1]+=lz[v]*(tr-((tl+tr)>>1));
    //operation
    lz[(v<<1)|1]+=lz[v];
    lz[v]=0LL;
    return;
}

void update(ll v,ll tl,ll tr,ll l,ll r,ll val,bool set,ll st[],ll lz[],bool f[])
{
    if(l>r)
    {
        return;
    }
    if(l==tl&&tr==r)
    {
        if(set)
        {
            //operation
            st[v]=lz[v]=0LL;
            f[v]=true;
        }
        //operation
        st[v]+=val*(tr-tl+1);
        //operation
        lz[v]+=val;
        return;
    }
    push(v,tl,tr,st,lz,f);
    update((v<<1),tl,((tl+tr)>>1),l,min(r,((tl+tr)>>1)),val,set,st,lz,f);
    update((v<<1)|1,((tl+tr)>>1)+1,tr,max(l,((tl+tr)>>1)+1),r,val,set,st,lz,f);
    //operation
    st[v]=st[(v<<1)]+st[(v<<1)|1];
    return;
}

ll query(ll v,ll tl,ll tr,ll l,ll r,ll st[],ll lz[],bool f[])
{
    if(l>r)
    {
        return 0LL;
    }
    if(l==tl&&tr==r)
    {
        return st[v];
    }
    push(v,tl,tr,st,lz,f);
    //operation
    return query((v<<1),tl,((tl+tr)>>1),l,min(r,((tl+tr)>>1)),st,lz,f)+query((v<<1)|1,((tl+tr)>>1)+1,tr,max(l,((tl+tr)>>1)+1),r,st,lz,f);
}
//LAZY SEGMENT TREE END

// SEGMENT TREE START
 void build(int v,int tl,int tr,int a[],long long st[]) // building the segment tree
{
    if(tl==tr) // when reaching the leaf node giving segment tree value the given array value
    {
        st[v]=a[tl];
        return;
    }
    int tm=((tl+tr)/2); // distributing the value of present node in two successor nodes
    build(2*v,tl,tm,a,st); // left end to middle
    build(2*v+1,tm+1,tr,a,st); // middle to right end
    st[v]=st[v*2]+st[v*2+1]; // giving value to the parent of the two succesor nodes
    return;
}

void update(int v,int tl,int tr,int pos,int val,long long st[])
{
    if(tl==tr&&tl==pos) // updating the value if the reached leaf node is equal to pos
    {
        st[v]=val;
        return;
    }
    if(tl>pos||tr<pos)
    {
        return; // avoiding segmentation fault
    }
    int tm=((tl+tr)/2);// distributing the value of present node in two successor nodes
    update(2*v,tl,tm,pos,val,st);// left end to middle
    update(2*v+1,tm+1,tr,pos,val,st);// middle to right end
    st[v]=st[v*2]+st[v*2+1]; // giving value to the parent of the two succesor nodes
    return;
}

long long query(int v,int tl,int tr,int l,int r,long long st[])
{
    if(tl==l&&tr==r) // returning the value of the corresponding node if given range equals the range of node
    {
        return st[v];
    }
    if(l>r) // avoiding excess traversal which is not required
    {
        return 0LL;
    }
    int tm=((tl+tr)/2);
    return query(v*2,tl,tm,l,std::min(tm,r),st)+query(v*2+1,tm+1,tr,std::max(tm+1,l),r,st); // (max):- cuz cant be less than left extremity, (min):- cuz cant be greater than righ extremity
}

//SEGMENT TREE END

// DISJOINT SET UNION START
ll fn(ll x,ll rn[]) // finding the component
{
    if(x==rn[x]) // Top of its component
        return x;
    else //making parent node of each node of the component the highest node
        return rn[x]=fn(rn[x],rn);
}

bool un(ll x,ll y,ll rn[],ll sz[])// union of components
{
    x=fn(x,rn);
    y=fn(y,rn);
    if(x==y)// if connected already
        return false;
    if(sz[x]<sz[y])// otherwise connectiing light to heavy by swapping
        swap(x,y);
    sz[x]+=sz[y];
    rn[y]=x;// making parent node;
    return true;
}

//DISJOINT SET UNION END
ll power(ll k)
{
    ll temp=1;
    REP(i,0,k-1)
    {
        temp=temp*2;
    }
    return temp;
}
bool compare(const pair<ll,ll>&a, const pair<ll,ll>&b)
{
    return a.S<b.S;
}
pair<int,int> mostFrequent(ll arr[], ll n)
{
    unordered_map<ll, ll> hash;
    for (ll i = 0; i < n; i++)
        hash[arr[i]]++;

    ll max_count = 0, res = -1;
    for (auto i : hash) {
        if (max_count < i.second) {
            res = i.first;
            max_count = i.second;
        }
    }
    pair<ll,ll> temp;
    temp.F=res;
    temp.S=max_count;
    return temp;
}
string findSum(string str1, string str2)
{
    // Before proceeding further, make sure length
    // of str2 is larger.
    if (str1.length() > str2.length())
        swap(str1, str2);

    // Take an empty string for storing result
    string str = "";

    // Calculate length of both string
    int n1 = str1.length(), n2 = str2.length();

    // Reverse both of strings
    reverse(str1.begin(), str1.end());
    reverse(str2.begin(), str2.end());

    int carry = 0;
    for (int i=0; i<n1; i++)
    {
        // Do school mathematics, compute sum of
        // current digits and carry
        int sum = ((str1[i]-'0')+(str2[i]-'0')+carry);
        str.push_back(sum%10 + '0');

        // Calculate carry for next step
        carry = sum/10;
    }

    // Add remaining digits of larger number
    for (int i=n1; i<n2; i++)
    {
        int sum = ((str2[i]-'0')+carry);
        str.push_back(sum%10 + '0');
        carry = sum/10;
    }

    // Add remaining carry
    if (carry)
        str.push_back(carry+'0');

    // reverse resultant string
    reverse(str.begin(), str.end());

    return str;
}
ll div(ll n)
{
    if (n % 2 == 0)
        return 2;
    for (ll i = 3; i * i <= n; i += 2) {
        if (n % i == 0)
            return i;
    }
    return n;
}
ll gcd(ll a, ll b){if(!b)return a;return gcd(b, a % b);}
ll lcm(ll a , ll b){return (a*b)/gcd(a,b);}
bool sec(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.F > b.F);
}
bool sec1(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.second > b.second);
}
ll msum(ll a[], ll size)
{
   ll max_so_far = a[0];
   ll curr_max = a[0];

   for (ll i = 1; i < size; i++)
   {
        curr_max = max(a[i], curr_max+a[i]);
        max_so_far = max(max_so_far, curr_max);
   }
   return max_so_far;
}
vector<ll> v[200010];
vector<bool> vis(200010,0);
set<ll> st;
ll um[200010];
void dfs(ll t)
{
    vis[t]=1;
    st.insert(um[t]);
    for(auto u:v[t])
    {
        if(vis[u]==0)
        {
            dfs(u);
        }
    }
}
int main()
{
    ios_base::sync_with_stdio(0);
	cin.tie(0);
    cout.tie(0);

    ll n,m,k;
    cin>>n>>m>>k;
    REP(i,1,n)
    {
        ll c;
        cin>>c;
        um[i]=c;
    }
    REP(i,0,m-1)
    {
        ll x,y;
        cin>>x>>y;
        v[x].PB(y);
        v[y].PB(x);
    }
    ll ans=0;
    REP(i,1,n)
    {
        if(vis[i]==0)
        {
            st.clear();
            dfs(i);
            ans=ans+(((ll)st.size())-1);
        }
    }
    cout<<ans;
    return 0;
}


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <climits>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <string.h>
#include <iomanip>
#include <ctype.h>

#define ll          long long int
#define ull         unsigned long long int
#define pb          push_back
#define pii         pair<int,int>
#define fp          first
#define sp          second
#define vi          vector<int>
#define vii         vector<pii>
#define mi          map<int,int>
#define mii         map<pii,int>
#define M_PI        3.14159265358979323846
#define mp          make_pair
#define sz(x)       (int)x.size()
#define hell        1000000007
#define forn(i,a,b)  for(int i=a;i<b;i++)
#define eps 1e9
#define all(a)      (a).begin(),(a).end()
const long long INF = (long long) 1e18+2;

using namespace std;
void solve();

void fastIO() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
}

int main(){
   fastIO();
    solve();
}
//void sieve();
//ll pw(ll k,ll x);
//ll gcd(ll x,ll y);
vi graph[200001];
void dfs(int x);
bool vis[200001];
map<int,int> mpi;
int col[200001];

void solve(){

  int n,m,k;
  cin>>n>>m>>k;

  forn(i,1,n+1){
    cin>>col[i];
  }

  forn(i,0,m)
  {
    int a,b;
    cin>>a>>b;
    graph[a].pb(b);
    graph[b].pb(a);
  }

  memset(vis,false,sizeof(vis));

  int ans=0;

  forn(i,1,n+1){
    if(vis[i]==false){
      mpi.clear();
      dfs(i);
      int last=0;
      int sum=0;
      for(auto it:mpi){
        sum+=it.second;
        last=max(last,it.second);
      }
      ans+=(sum-last);
    }
  }
  cout<<ans;
}

void dfs(int x){
  vis[x]=true;
  mpi[col[x]]++;

  for(int i=0;i<graph[x].size();i++){
    int v=graph[x][i];
    if(vis[v]==false)
    dfs(v);
  }
}

///Before submit=>
///    *check for integer overflow,array bounds
///    *check for n=1

/*ll gcd(ll x,ll y){
  if(x==0)
  return y;
  else
  return gcd(y%x,x);
}*/

/*ll pw(ll k,ll x){
  if(x==0)
  return 1;
  if(x&1)
  return ((pw(k,x-1)%hell)*k%hell)%hell;
  else
  return ((pw(k,x/2)%hell)*(pw(k,x/2)%hell))%hell;
}*/

/*void sieve(){

  for(int i=2;i<=1000000;i++){
    if(prime[i]==true){
      for(int j=i*i;j<=1000000;j+=i)
      prime[j]=false;
    }
  }

}*/


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <climits>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <string.h>
#include <iomanip>
#include <ctype.h>

#define ll          long long int
#define ull         unsigned long long int
#define pb          push_back
#define pii         pair<int,int>
#define fp          first
#define sp          second
#define vi          vector<int>
#define vii         vector<pii>
#define mi          map<int,int>
#define mii         map<pii,int>
#define M_PI        3.14159265358979323846
#define mp          make_pair
#define sz(x)       (int)x.size()
#define hell        1000000007
#define forn(i,a,b)  for(int i=a;i<b;i++)
#define eps 1e9
#define all(a)      (a).begin(),(a).end()
const long long INF = (long long) 1e18+2;

using namespace std;
void solve();

void fastIO() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
}

int main(){
   fastIO();
    solve();
}
//void sieve();
//ll pw(ll k,ll x);
//ll gcd(ll x,ll y);
vi graph[200001];
void dfs(int x);
bool vis[200001];
map<int,int> mpi;
int col[200001];

void solve(){

  int n,m,k;
  cin>>n>>m>>k;

  forn(i,1,n+1){
    cin>>col[i];
  }

  forn(i,0,m)
  {
    int a,b;
    cin>>a>>b;
    graph[a].pb(b);
    graph[b].pb(a);
  }

  memset(vis,false,sizeof(vis));

  int ans=0;

  forn(i,1,n+1){
    if(vis[i]==false){
      mpi.clear();
      dfs(i);
      int last;
      for(auto it:mpi){
        ans+=it.second;
        last=it.second;
      }
      ans-=last;
    }
  }
  cout<<ans;
}

void dfs(int x){
  vis[x]=true;
  mpi[col[x]]++;
  for(int i=0;i<graph[x].size();i++){
    int v=graph[x][i];
    if(vis[v]==false)
    dfs(v);
  }
}

///Before submit=>
///    *check for integer overflow,array bounds
///    *check for n=1

/*ll gcd(ll x,ll y){
  if(x==0)
  return y;
  else
  return gcd(y%x,x);
}*/

/*ll pw(ll k,ll x){
  if(x==0)
  return 1;
  if(x&1)
  return ((pw(k,x-1)%hell)*k%hell)%hell;
  else
  return ((pw(k,x/2)%hell)*(pw(k,x/2)%hell))%hell;
}*/

/*void sieve(){

  for(int i=2;i<=1000000;i++){
    if(prime[i]==true){
      for(int j=i*i;j<=1000000;j+=i)
      prime[j]=false;
    }
  }

}*/


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <climits>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <string.h>
#include <iomanip>
#include <ctype.h>

#define ll          long long int
#define ull         unsigned long long int
#define pb          push_back
#define pii         pair<int,int>
#define fp          first
#define sp          second
#define vi          vector<int>
#define vii         vector<pii>
#define mi          map<int,int>
#define mii         map<pii,int>
#define M_PI        3.14159265358979323846
#define mp          make_pair
#define sz(x)       (int)x.size()
#define hell        1000000007
#define forn(i,a,b)  for(int i=a;i<b;i++)
#define eps 1e9
#define all(a)      (a).begin(),(a).end()
const long long INF = (long long) 1e18+2;

using namespace std;
void solve();

void fastIO() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
}

int main(){
   fastIO();
    solve();
}
//void sieve();
//ll pw(ll k,ll x);
//ll gcd(ll x,ll y);
vi graph[200001];
void dfs(int x);
bool vis[200001];
map<int,int> mpi;

void solve(){

  int n,m,k;
  cin>>n>>m>>k;

  int col[n+1];
  forn(i,1,n+1){
    cin>>col[i];
  }

  forn(i,0,m)
  {
    int a,b;
    cin>>a>>b;
    graph[col[a]].pb(col[b]);
    graph[col[b]].pb(col[a]);
  }

  memset(vis,false,sizeof(vis));

  int ans=0;

  forn(i,1,n+1){
    if(vis[i]==false){
      mpi.clear();
      dfs(i);
      int last;
      for(auto it:mpi){
        ans+=it.second;
        last=it.second;
      }
      ans-=last;
    }
  }
  cout<<ans;
}

void dfs(int x){
  vis[x]=true;
  mpi[x]++;
  for(int i=0;i<graph[x].size();i++){
    int v=graph[x][i];
    if(vis[v]==false)
    dfs(v);
  }
}

///Before submit=>
///    *check for integer overflow,array bounds
///    *check for n=1

/*ll gcd(ll x,ll y){
  if(x==0)
  return y;
  else
  return gcd(y%x,x);
}*/

/*ll pw(ll k,ll x){
  if(x==0)
  return 1;
  if(x&1)
  return ((pw(k,x-1)%hell)*k%hell)%hell;
  else
  return ((pw(k,x/2)%hell)*(pw(k,x/2)%hell))%hell;
}*/

/*void sieve(){

  for(int i=2;i<=1000000;i++){
    if(prime[i]==true){
      for(int j=i*i;j<=1000000;j+=i)
      prime[j]=false;
    }
  }

}*/


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <climits>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <map>
#include <queue>
#include <string.h>
#include <iomanip>
#include <ctype.h>
#define ll long long int
#define mod 1000000007
#define MAXN 200001
using namespace std;
int n,m,k;
int c[200001];
vector<int> temp;
void dfs(int i);
int vis[200001];
vector<int> graph[200001];
int main(){
  cin>>n>>m>>k;
  for(int i=1;i<=n;i++)
  cin>>c[i];
  for(int i=0;i<m;i++)
  {
    int x,y;
    cin>>x>>y;
    graph[x].push_back(y);
    graph[y].push_back(x);
  }
  memset(vis,-1,sizeof(vis));
  int ans=0;
  for(int i=1;i<=n;i++){
    if(vis[i]==-1){
      dfs(i);
      sort(temp.begin(),temp.end());
      int h=temp[temp.size()-1];
      int f,l;
      f=1;
      l=-1;
      int ch=temp[0];
      for(int j=1;j<temp.size();j++){
        if(temp[j]==ch)
        f++;
        else
        {
          l=max(l,f);
          ch=temp[j];
        }
      }
       ans=ans+(temp.size()-l);
       temp.clear();
    }
  }
cout<<ans;
}
void dfs(int i){
  vis[i]=1;
  temp.push_back(i);
  for(int j=0;j<graph[i].size();j++)
  {
    if(vis[graph[i][j]]==-1)
    dfs(graph[i][j]);
  }
}


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <climits>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <string.h>
#include <iomanip>
#include <ctype.h>

#define ll          long long int
#define ull         unsigned long long int
#define pb          push_back
#define pii         pair<int,int>
#define fp          first
#define sp          second
#define vi          vector<int>
#define vii         vector<pii>
#define mi          map<int,int>
#define mii         map<pii,int>
#define M_PI        3.14159265358979323846
#define mp          make_pair
#define sz(x)       (int)x.size()
#define hell        1000000007
#define forn(i,a,b)  for(int i=a;i<b;i++)
#define eps 1e9
#define all(a)      (a).begin(),(a).end()
const long long INF = (long long) 1e18+2;

using namespace std;
void solve();

void fastIO() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
}

int main(){
   fastIO();
    solve();
}
//void sieve();
//ll pw(ll k,ll x);
//ll gcd(ll x,ll y);
vi graph[200001];
void dfs(int x);
bool vis[200001];
unordered_set<int> st;

void solve(){

  int n,m,k;
  cin>>n>>m>>k;

  int col[n+1];
  forn(i,1,n+1){
    cin>>col[i];
  }

  forn(i,0,m)
  {
    int a,b;
    cin>>a>>b;
    graph[col[a]].pb(col[b]);
    graph[col[b]].pb(col[a]);
  }

  memset(vis,false,sizeof(vis));

  int ans=0;

  forn(i,1,n+1){
    if(vis[i]==false){
      st.clear();
      dfs(i);
      ans+=st.size()-1;
    }
  }
  cout<<ans;
}

void dfs(int x){
  vis[x]=true;
  st.insert(x);
  for(int i=0;i<graph[x].size();i++){
    int v=graph[x][i];
    if(vis[v]==false)
    dfs(v);
  }
}

///Before submit=>
///    *check for integer overflow,array bounds
///    *check for n=1

/*ll gcd(ll x,ll y){
  if(x==0)
  return y;
  else
  return gcd(y%x,x);
}*/

/*ll pw(ll k,ll x){
  if(x==0)
  return 1;
  if(x&1)
  return ((pw(k,x-1)%hell)*k%hell)%hell;
  else
  return ((pw(k,x/2)%hell)*(pw(k,x/2)%hell))%hell;
}*/

/*void sieve(){

  for(int i=2;i<=1000000;i++){
    if(prime[i]==true){
      for(int j=i*i;j<=1000000;j+=i)
      prime[j]=false;
    }
  }

}*/


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <climits>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <string.h>
#include <iomanip>
#include <ctype.h>

#define ll          long long int
#define ull         unsigned long long int
#define pb          push_back
#define pii         pair<int,int>
#define fp          first
#define sp          second
#define vi          vector<int>
#define vii         vector<pii>
#define mi          map<int,int>
#define mii         map<pii,int>
#define M_PI        3.14159265358979323846
#define mp          make_pair
#define sz(x)       (int)x.size()
#define hell        1000000007
#define forn(i,a,b)  for(int i=a;i<b;i++)
#define eps 1e9
#define all(a)      (a).begin(),(a).end()
const long long INF = (long long) 1e18+2;

using namespace std;
void solve();

void fastIO() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
}

int main(){
   fastIO();
    solve();
}
//void sieve();
//ll pw(ll k,ll x);
//ll gcd(ll x,ll y);
vi graph[200001];
void dfs(int x);
bool vis[200001];
map<int,int> mpi;
int col[200001];

void solve(){

  int n,m,k;
  cin>>n>>m>>k;

  forn(i,1,n+1){
    cin>>col[i];
  }

  forn(i,0,m)
  {
    int a,b;
    cin>>a>>b;
    graph[a].pb(b);
    graph[b].pb(a);
  }

  memset(vis,false,sizeof(vis));

  int ans=0;

  forn(i,1,n+1){
    if(vis[i]==false){
      mpi.clear();
      dfs(i);
      int last=0;
      int sum=0;
      for(auto it:mpi){
        sum+=it.second;
        last=max(last,it.second)
      }
      ans+=(sum-last);
    }
  }
  cout<<ans;
}

void dfs(int x){
  vis[x]=true;
  mpi[col[x]]++;

  for(int i=0;i<graph[x].size();i++){
    int v=graph[x][i];
    if(vis[v]==false)
    dfs(v);
  }
}

///Before submit=>
///    *check for integer overflow,array bounds
///    *check for n=1

/*ll gcd(ll x,ll y){
  if(x==0)
  return y;
  else
  return gcd(y%x,x);
}*/

/*ll pw(ll k,ll x){
  if(x==0)
  return 1;
  if(x&1)
  return ((pw(k,x-1)%hell)*k%hell)%hell;
  else
  return ((pw(k,x/2)%hell)*(pw(k,x/2)%hell))%hell;
}*/

/*void sieve(){

  for(int i=2;i<=1000000;i++){
    if(prime[i]==true){
      for(int j=i*i;j<=1000000;j+=i)
      prime[j]=false;
    }
  }

}*/


#include<bits/stdc++.h>
using namespace std;
vector<int>adj[200005];
int vis[200005],ans;
map<int,int>m1;
int col[200005],k1;
void dfs(int s)
{
    vis[s]=1;
    m1[col[s]]++;
    k1++;
    ans=max(ans,m1[col[s]]);
    for(int i=0;i<(int)adj[s].size();i++)
    {
        if(!vis[adj[s][i]])
        {
            dfs(adj[s][i]);
        }
    }
}
int main()
{
    int n,m,k,a,b,i;
    cin>>n>>m>>k;
    for(i=1;i<=n;i++)
    {
        cin>>col[i];
    }
    for(i=0;i<m;i++)
    {
        cin>>a>>b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    int sum=0;
    for(i=1;i<=n;i++)
    {
        k1=0;
        ans=0;
        if(!vis[i])
        {
            dfs(i);
            sum+=(k1-ans);
        }
    }
    cout<<sum;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
vector<int>adj[200005];
int vis[200005],ans;
map<int,int>m1,m2;
int col[200005],k1;
void dfs(int s)
{
    vis[s]=1;
    if(m2[col[s]]!=1)
    {
    k1+=m1[col[s]];
    m2[col[s]]=1;
    }
    ans=max(ans,m1[col[s]]);
    for(int i=0;i<(int)adj[s].size();i++)
    {
        if(!vis[adj[s][i]])
        {
            dfs(adj[s][i]);
        }
    }
}
int main()
{
    int n,m,k,a,b,i;
    cin>>n>>m>>k;
    for(i=1;i<=n;i++)
    {
        cin>>col[i];
    }
    for(i=0;i<m;i++)
    {
        cin>>a>>b;
        adj[a].push_back(b);
        adj[b].push_back(a);
        m1[col[a]]++;
        m1[col[b]]++;
    }
    int sum=0;
    for(i=1;i<=n;i++)
    {
        k1=0;
        ans=0;
        if(!vis[i])
        {
            dfs(i);
            sum+=(k1-ans);
        }
    }
    cout<<sum;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
vector<int>adj[200005];
int vis[200005],ans;
map<int,int>m1;
int col[200005],k1;
void dfs(int s)
{
    vis[s]=1;
    ans=max(ans,m1[s]);
    for(int i=0;i<(int)adj[s].size();i++)
    {
        k1++;
        if(!vis[adj[s][i]])
        {
            dfs(adj[s][i]);
        }
    }
}
int main()
{
    int n,m,k,a,b,i;
    cin>>n>>m>>k;
    for(i=1;i<=n;i++)
    {
        cin>>col[i];
    }
    for(i=0;i<m;i++)
    {
        cin>>a>>b;
        adj[a].push_back(b);
        adj[b].push_back(a);
        m1[col[a]]++;
        m1[col[b]]++;
    }
    int sum=0;
    for(i=1;i<=n;i++)
    {
        k1=0;
        ans=0;
        if(!vis[i])
        {
            dfs(i);
            sum+=(k1-ans);
        }
    }
    cout<<sum;
    return 0;
}