//In the name of Allah :)
#include <bits/stdc++.h>
using namespace std;
string to_string(char c) { return string(1,c); }
string to_string(bool b) { return b ? "true" : "false"; }
string to_string(const char* s) { return (string)s; }
string to_string(string s) { return s; }
template<class A> string to_string(complex<A> c) {
	stringstream ss; ss << c; return ss.str(); }
string to_string(vector<bool> v) {
	string res = "{"; for(int i = 0; i < (int)v.size(); i++) res += char('0'+v[i]);
	res += "}"; return res; }
template<size_t SZ> string to_string(bitset<SZ> b) {
	string res = ""; for(size_t i = 0; i < SZ; i++) res += char('0'+b[i]);
	return res; }
template<class A, class B> string to_string(pair<A,B> p);
template<class T> string to_string(T v) { // containers with begin(), end()
	bool fst = 1; string res = "{";
	for (const auto& x: v) {
		if (!fst) res += ", ";
		fst = 0; res += to_string(x);
	}
	res += "}"; return res;
}
template<class A, class B> string to_string(pair<A,B> p) {
	return "("+to_string(p.first)+", "+to_string(p.second)+")"; }
void DBG() { cerr << "]" << endl; }
template<class H, class... T> void DBG(H h, T... t) {
	cerr << to_string(h); if (sizeof...(t)) cerr << ", ";
	DBG(t...); }
#ifdef DEBUG// compile with -DLOCAL
#define wis(...) cerr << "LINE(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "] : [", DBG(__VA_ARGS__)
#else
#define wis(...) 0
#endif
typedef long long ll;
#define all(x) (x).begin(), (x).end()
const int MOD = 1e9 + 7, INF = 1e9 + 5;
const ll LONG_INF = 1e18 + 10;
inline ll powmod(ll a, ll b){ll res=1;for(;b;b>>=1,a=a*a%MOD)if(b&1)res=res*a%MOD;return res;}
inline ll power(ll a, ll b){ll res=1;for(;b;b>>=1,a=a*a)if(b&1)res=res*a;return res;}

const int MAXN = 2000 + 10;
vector<int> adj[MAXN];
int g[MAXN][MAXN];

struct edge {
	int u, v;
	bool I, O;
	void read(int i){
		cin >> u >> v;
		u--, v--;
		adj[u].push_back(v);
		adj[v].push_back(u);
		g[v][u] = i;
		g[u][v] = i;
		I = O = 1;
	}
} edges[MAXN];

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m;
	cin >> n >> m;
	for(int i = 0; i < m; i++){
		edges[i].read(i);
	}
	string ans(m, '*');
	queue<int> bfs;
	set<int> have;
	for(int i = 0; i < m; i++){
		have.insert(i);
	}
	while(have.size()){
		bfs.push(*have.begin());
		have.erase(have.begin());
		while(bfs.size()){
			int i = bfs.front();
			bfs.pop();
			if(edges[i].I){
				assert(ans[i] == '*');
				ans[i] = 'i';
				set<int> nums;
				for(int j = edges[i].u + 1; j != edges[i].v; j = (j + 1) % n){
					nums.insert(j);
				}
				for(int q : nums){
					for(int j : adj[q]){
						if(nums.count(j) || j == edges[i].v || j == edges[i].u){
							continue;
						}
						int tmp = g[q][j];
						if(have.count(tmp)){
							have.erase(tmp);
							bfs.push(tmp);
						}
						assert(edges[tmp].I == 1);
						edges[tmp].I = 0;
					}
				}
				continue;
			}

			if(edges[i].O){
				assert(ans[i] == '*');
				ans[i] = 'o';
				set<int> nums;
				for(int j = edges[i].u + 1; j != edges[i].v; j = (j + 1) % n){
					nums.insert(j);
				}
				for(int q : nums){
					for(int j : adj[q]){
						if(nums.count(j) || j == edges[i].v || j == edges[i].u){
							continue;
						}
						int tmp = g[q][j];
						if(have.count(tmp)){
							have.erase(tmp);
							bfs.push(tmp);
						}
						assert(edges[tmp].O == 1);
						edges[tmp].O = 0;
					}
				}
				continue;
			}
			cout << "Impossible\n";
			return 0;
		}
	}
	cout << ans << '\n';
}


#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifndef ONLINE_JUDGE
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
}
template<typename X, typename Y>
istream& operator>>(istream& in, pair<X, Y> &a) {
	in >> a.first >> a.second;
	return in;
}
template<typename T>
void getv(T& i) {
	cin >> i;
}
template<typename T, typename ... Ns>
void getv(vector<T>& v, int n, Ns ... ns) {
	v.resize(n);
	for (auto& i : v)
		getv(i, ns...);
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
bool ins(pi a, pi b) {
	if (a.first < b.first)
		swap(a, b);
	return a.first > b.first &&  a.first < b.second && a.second > b.second;
}

int n, m, col[105], f, t;
vpi a;
vvi g, gt;
vi topo, vis, scc;

void dfs1(int v) {
	vis[v] = 1;
	for(int i : g[v]) {
		if(vis[i] == 0)
			dfs1(i);
	}
	topo.pb(v);
}
void dfs2(int v, int cl) {
	scc[v] = cl;
	for(int i : gt[v]) {
		if(scc[i] == 0)
			dfs2(i, cl);
	}
}

int main() {
	doin();
	cin >> n >> m;
	getv(a, m);
	for (auto& i : a)
		if (i.first > i.second)
			swap(i.first, i.second);
	g.resize(2 * m + 5);
	gt.resize(2 * m + 5);
	vis.resize(2 * m + 5);
	scc.resize(2 * m + 5);
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < m; j++) {
			if(i == j) continue;
			if(ins(a[i], a[j])) {
				g[2*i].pb(2*j+1);
				g[2*j].pb(2*i+1);
				gt[2*i+1].pb(2*j);
				gt[2*j+1].pb(2*i);
			}
		}
	}
	int M = 2*m, cl = 1;
	for(int i = 0; i < M; i++) {
		if(!vis[i])
			dfs1(i);
	}
	for(int i = M-1; i >= 0; i--) {
		if(!scc[topo[i]])
			dfs2(topo[i], cl++);
	}
	for(int i = 0; i < M; i++) {
		if(scc[i] == scc[i^1])
			return cout << "Impossible", 0;
	}
	for(int i = 1; i < M; i+=2) {
		cout << ((scc[i]>scc[i^1]) ? 'i' : 'o');
	}
}


#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifndef ONLINE_JUDGE
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
}
template<typename X, typename Y>
istream& operator>>(istream& in, pair<X, Y> &a) {
	in >> a.first >> a.second;
	return in;
}
template<typename T>
void getv(T& i) {
	cin >> i;
}
template<typename T, typename ... Ns>
void getv(vector<T>& v, int n, Ns ... ns) {
	v.resize(n);
	for (auto& i : v)
		getv(i, ns...);
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
bool ins(pi a, pi b) {
	if (a.first < b.first)
		swap(a, b);
	return a.first > b.first &&  a.first < b.second && a.second > b.second;
}

int n, m, col[105], f, t;
vpi a;
vvi g, gt;
vi topo, vis, scc;

void dfs1(int v) {
	vis[v] = 1;
	for(int i : g[v]) {
		if(vis[i] == 0)
			dfs1(i);
	}
	topo.pb(v);
}
void dfs2(int v, int cl) {
	scc[v] = cl;
	for(int i : g[v]) {
		if(scc[i] == 0)
			dfs2(i, cl);
	}
}

int main() {
	doin();
	cin >> n >> m;
	getv(a, m);
	for (auto& i : a)
		if (i.first > i.second)
			swap(i.first, i.second);
	g.resize(2 * m + 5);
	gt.resize(2 * m + 5);
	vis.resize(2 * m + 5);
	scc.resize(2 * m + 5);
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < m; j++) {
			if(i == j) continue;
			if(ins(a[i], a[j])) {
				g[2*i].pb(2*j+1);
				g[2*j].pb(2*i+1);
				g[2*i+1].pb(2*j);
				g[2*j+1].pb(2*i);
			}
		}
	}
	int M = 2*m, cl = 1;
	for(int i = 0; i < M; i++) {
		if(!vis[i])
			dfs1(i);
	}
	for(int i = M-1; i >= 0; i--) {
		if(!scc[topo[i]])
			dfs2(topo[i], cl++);
	}
	for(int i = 0; i < M; i++) {
		if(scc[i] == scc[i^1])
			return cout << "Impossible", 0;
	}
	for(int i = 1; i < M; i+=2) {
		cout << ((scc[i]>scc[i^1]) ? 'i' : 'o');
	}
}


#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifndef ONLINE_JUDGE
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
}
template<typename X, typename Y>
istream& operator>>(istream& in, pair<X, Y> &a) {
	in >> a.first >> a.second;
	return in;
}
template<typename T>
void getv(T& i) {
	cin >> i;
}
template<typename T, typename ... Ns>
void getv(vector<T>& v, int n, Ns ... ns) {
	v.resize(n);
	for (auto& i : v)
		getv(i, ns...);
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
bool ins(pi a, pi b) {
	if (a.first > b.first)
		swap(a, b);
	return a.second > b.first;
}

int n, m, col[105], f, t;
vpi a;
vvi g, gt;
vi topo, vis, scc;

void dfs1(int v) {
	vis[v] = 1;
	for(int i : g[v]) {
		if(vis[i] == 0)
			dfs1(i);
	}
	topo.pb(v);
}
void dfs2(int v, int cl) {
	scc[v] = cl;
	for(int i : gt[v]) {
		if(scc[i] == 0)
			dfs2(i, cl);
	}
}

int main() {
	doin();
	cin >> n >> m;
	getv(a, m);
	for (auto& i : a)
		if (i.first > i.second)
			swap(i.first, i.second);
	g.resize(2 * m + 5);
	gt.resize(2 * m + 5);
	vis.resize(2 * m + 5);
	scc.resize(2 * m + 5);
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < m; j++) {
			if(i == j) continue;
			if(ins(a[i], a[j])) {
				g[2*i].pb(2*j+1);
				g[2*j].pb(2*i+1);
				gt[2*i+1].pb(2*j);
				gt[2*j+1].pb(2*i);
			}
		}
	}
	int M = 2*m, cl = 1;
	for(int i = 0; i < M; i++) {
		if(!vis[i])
			dfs1(i);
	}
	for(int i = M-1; i >= 0; i--) {
		if(!scc[topo[i]])
			dfs2(topo[i], cl++);
	}
	for(int i = 0; i < M; i++) {
		if(scc[i] == scc[i^1])
			return cout << "Impossible", 0;
	}
	for(int i = 1; i < M; i+=2) {
		cout << ((scc[i]>scc[i^1]) ? 'i' : 'o');
	}
}


#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifndef ONLINE_JUDGE
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
}
template<typename X, typename Y>
istream& operator>>(istream& in, pair<X, Y> &a) {
	in >> a.first >> a.second;
	return in;
}
template<typename T>
void getv(T& i) {
	cin >> i;
}
template<typename T, typename ... Ns>
void getv(vector<T>& v, int n, Ns ... ns) {
	v.resize(n);
	for (auto& i : v)
		getv(i, ns...);
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
bool ins(pi a, pi b) {
	if (a.first > b.first)
		swap(a, b);
	return a.second > b.first;
}

int n, m, col[105], f, t;
vpi a;
vvi g;
vi topo, vis, scc;

void dfs1(int v) {
	vis[v] = 1;
	for(int i : g[v]) {
		if(vis[i] == 0)
			dfs1(i);
	}
	topo.pb(v);
}
void dfs2(int v, int cl) {
	scc[v] = cl;
	for(int i : g[v]) {
		if(!scc[i])
			dfs2(i, cl);
	}
}

int main() {
	doin();
	cin >> n >> m;
	getv(a, m);
	for (auto& i : a)
		if (i.first > i.second)
			swap(i.first, i.second);
	g.resize(2 * m + 5);
	vis.resize(2 * m + 5);
	scc.resize(2 * m + 5);
	for (int i = 0; i < m; i++) {
		for (int j = i+1; j < m; j++) {
			if(ins(a[i], a[j])) {
				g[2*i+1].pb(2*j);
				g[2*j+1].pb(2*i);
			}
		}
	}
	int M = 2*m, cl = 1;
	for(int i = 0; i < M; i++) {
		if(!vis[i])
			dfs1(i);
	}
	for(int i = M-1; i >= 0; i--) {
		if(!scc[topo[i]])
			dfs2(topo[i], cl++);
	}
	for(int i = 0; i < M; i++) {
		if(scc[i] == scc[i^1])
			return cout << "Impossible", 0;
	}
	for(int i = 0; i < M; i+=2) {
		cout << ((scc[i]>scc[i^1]) ? 'i' : 'o');
	}
}


#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifndef ONLINE_JUDGE
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
}
template<typename X, typename Y>
istream& operator>>(istream& in, pair<X, Y> &a) {
	in >> a.first >> a.second;
	return in;
}
template<typename T>
void getv(T& i) {
	cin >> i;
}
template<typename T, typename ... Ns>
void getv(vector<T>& v, int n, Ns ... ns) {
	v.resize(n);
	for (auto& i : v)
		getv(i, ns...);
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
bool ins(pi a, pi b) {
	if (a.first < b.first)
		swap(a, b);
	return a.first > b.first &&  a.first < b.second && a.second > b.second;
}

int n, m, col[105], f, t;
vpi a;

int main() {
	doin();
	cin >> n >> m;
	getv(a, m);
	for (auto& i : a)
		if (i.first > i.second)
			swap(i.first, i.second);
	for (int i = 0; i < m; i++) {
		for (int j = i+1; j < m; j++) {
			if(i == j) continue;
			if(ins(a[i], a[j])) {
				col[j] = col[i]^1;
			}
		}
	}
	for (int i = 0; i < m; i++) {
		for (int j = i+1; j < m; j++) {
			if(ins(a[i], a[j]) && col[i] == col[j]) {
				cout << "Impossible";
				return 0;
			}
		}
	}
	for(int i = 0; i < m; i++)
		cout << (col[i]?'o':'i');
}


#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifndef ONLINE_JUDGE
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
}
template<typename X, typename Y>
istream& operator>>(istream& in, pair<X, Y> &a) {
	in >> a.first >> a.second;
	return in;
}
template<typename T>
void getv(T& i) {
	cin >> i;
}
template<typename T, typename ... Ns>
void getv(vector<T>& v, int n, Ns ... ns) {
	v.resize(n);
	for (auto& i : v)
		getv(i, ns...);
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
bool ins(pi a, pi b) {
	if (a.first < b.first)
		swap(a, b);
	return a.first > b.first &&  a.first < b.second && a.second > b.second;
}

int n, m, col[105], f, t;
vpi a;

int main() {
	doin();
	cin >> n >> m;
	getv(a, m);
	for (auto& i : a)
		if (i.first > i.second)
			swap(i.first, i.second);
	for (int i = 0; i < m; i++) {
		for (int j = i+1; j < m; j++) {
			if(i == j) continue;
			if(ins(a[i], a[j])) {
				col[j] = col[i]^1;
			}
		}
	}
	for (int i = 0; i < m; i++) {
		for (int j = i+1; j < m; j++) {
			if(ins(a[i], a[j]) && col[i] == col[j]) {
				cout << "Impossible" << i << " " << j;
				return 0;
			}
		}
	}
	for(int i = 0; i < m; i++)
		cout << (col[i]?'o':'i');
}


#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifndef ONLINE_JUDGE
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
}
template<typename X, typename Y>
istream& operator>>(istream& in, pair<X, Y> &a) {
	in >> a.first >> a.second;
	return in;
}
template<typename T>
void getv(T& i) {
	cin >> i;
}
template<typename T, typename ... Ns>
void getv(vector<T>& v, int n, Ns ... ns) {
	v.resize(n);
	for (auto& i : v)
		getv(i, ns...);
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
bool ins(pi a, pi b) {
	if (a.first > b.first)
		swap(a, b);
	return a.second > b.first &&  a.first != b.first && a.second != b.second;
}

int n, m, col[105], f, t;
vpi a;

int main() {
	doin();
	cin >> n >> m;
	getv(a, m);
	for (auto& i : a)
		if (i.first > i.second)
			swap(i.first, i.second);
	for (int i = 0; i < m; i++) {
		for (int j = i+1; j < m; j++) {
			if(i == j) continue;
			if(ins(a[i], a[j])) {
				col[j] = col[i]^1;
			}
		}
	}
	for (int i = 0; i < m; i++) {
		for (int j = i+1; j < m; j++) {
			if(ins(a[i], a[j]) && col[i] == col[j]) {
				cout << "Impossible";
				return 0;
			}
		}
	}
	for(int i = 0; i < m; i++)
		cout << (col[i]?'o':'i');
}


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

typedef long long ll;

#define fastio ios_base :: sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr)
#define pb push_back
#define int long long
#define S second
#define F first
const int MAXN = 1000 + 7;

int n, m, a[MAXN], b[MAXN];
bool mark[MAXN], c[MAXN], bad;
vector<int>adj[MAXN];

void dfs(int v){
    mark[v] = 1;
    for(auto u : adj[v]){
        if(!mark[u]){
            c[u] = 1 - c[v];
            dfs(u);
        }else{
            if(c[u] == c[v])bad = 1;
        }
    }
    return;
}
int32_t main(){
    fastio;
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        cin >> a[i] >> b[i];
        if(a[i] > b[i])swap(a[i], b[i]);
        for(int j = 0; j < i; j++){
            if((a[i] > a[j] && a[i] < b[j] && b[i] > b[j])
                    || (a[i] < a[j] && b[i] > a[j] && b[i] < b[j])){
                adj[i].pb(j), adj[j].pb(i);
            }
        }
    }
    dfs(0);
    if(bad)return cout << "Impossible" << endl, 0;
    for(int i = 0; i < m; i ++){
        if(c[i])cout << 'o';
        else cout << 'i';
    }
    cout << endl;
    return 0;
}


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

typedef long long ll;

#define fastio ios_base :: sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr)
#define pb push_back
#define int long long
#define S second
#define F first
const int MAXN = 1000 + 7;

int n, m, a[MAXN], b[MAXN];
bool mark[MAXN], c[MAXN], bad;
vector<int>adj[MAXN];

void dfs(int v){
    mark[v] = 1;
    for(auto u : adj[v]){
        if(!mark[u]){
            c[u] = 1 - c[v];
            dfs(u);
        }else{
            if(c[u] == c[v])bad = 1;
        }
    }
    return;
}
int32_t main(){
    fastio;
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        cin >> a[i] >> b[i];
    }
    for(int i = 0; i < m; i ++){
        for(int j = i + 1; j < m; j ++){
            pair<int, int> arr[] ={{a[i], 0}, {b[i], 0}, {a[j], 1}, {b[j], 1}};
            sort(arr, arr + 4);
            if(!(arr[0].F < arr[1].F && arr[1].F < arr[2].F && arr[2].F < arr[3].F))continue;
            bool ed = 1;
            for(int k = 0; k < 4; k ++){
                if(arr[k].S == arr[(k + 1)%4].S)ed = 0;
            }
            if(ed){
                //cout << a[i] << "," << b[i] << "<->" << a[j] << "," << b[j] << endl;
                adj[i].pb(j), adj[j].pb(i);
            }
        }
    }
    dfs(0);
    if(bad)return cout << "Impossible" << endl, 0;
    for(int i = 0; i < m; i ++){
        if(c[i])cout << 'o';
        else cout << 'i';
    }
    cout << endl;
    return 0;
}


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

typedef long long ll;

#define fastio ios_base :: sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr)
#define pb push_back
#define int long long
#define S second
#define F first
const int MAXN = 1000 + 7;

int n, m, a[MAXN], b[MAXN];
bool mark[MAXN], c[MAXN], bad;
vector<int>adj[MAXN];

void dfs(int v){
    mark[v] = 1;
    for(auto u : adj[v]){
        if(!mark[u]){
            c[u] = 1 - c[v];
            dfs(u);
        }else{
            if(c[u] == c[v])bad = 1;
        }
    }
    return;
}
void dfs_all(){
    for(int i = 0; i < m; i ++){
        if(!mark[i])dfs(i);
    }
    return;
}
int32_t main(){
    fastio;
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        cin >> a[i] >> b[i];
        if(a[i] > b[i])swap(a[i], b[i]);
        for(int j = 0; j < i; j++){
            if((b[j] > b[i] && a[j] < b[i] && a[j] > a[i]) || (a[j] < a[i] && b[j] < b[i] && b[j] > a[i])){
                adj[i].pb(j), adj[j].pb(i);
            }
        }
    }
    dfs_all();
    if(bad)return cout << "Impossible" << endl, 0;
    for(int i = 0; i < m; i ++){
        if(c[i])cout << 'o';
        else cout << 'i';
    }
    cout << endl;
    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;
void solve();

int n,m;
vector<pii> R,RO;
vector<pii> I,O;

bool intersect(const pii& r , const vector<pii> IO){
    for(const auto io : IO){
        if((r.first > io.first && r.first < io.second && r.second > io.second) ||
          io.first > r.first && io.first < r.second && io.second > r.second)
            return true;
    }
    return false;
}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

    RO.resize(R.size());
    copy(R.begin(), R.end(), RO.begin()); //original order

    //sort(begin(R), end(R));

    for(const auto r : R){
       // cerr<<r.first<<" " <<r.second<<endl;
        if(!intersect(r,I)){
          //  cerr<<" I " <<endl;;
            I.push_back(r);
        }
        else if(!intersect(r,O)){
           // cerr<<" O " <<endl;;
            O.push_back(r);
        }
        else
        {
            cout<<"Impossible"<<endl;
            return 0;
        }
    }
    for(const auto r : RO){
        if(find(I.begin(), I.end(), r) != I.end())
            cout<<"i";
        else
            cout<<"o";
    }

    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;

int n,m;
vector<pii> R,RO;
vector<pii> I,O;
set<pii> D;

void print(vector<pii>& V){
 for(const auto p : V){
  cerr<<"("<<p.first<<" "<<p.second<<"), ";
 }
    cerr<<endl;
}

bool is_inside(const pii& r , const pii& r1){
  return
      r.first >= r1.first && r.second<=r1.second;
}

bool intersect(const pii& r , const pii& r1){
  return
      r.first > r1.first &&  r.first < r1.second && r.second > r1.second;
}

bool can_add(const pii& r , const vector<pii> IO){
    if(IO.size()<=0)
        return true;

    for(const auto io : IO){
        if(!( is_inside(r,io) || is_inside(io,r)  || (!intersect(r,io) && !intersect(io,r) ) )){
            cerr<<"cannot add "<<"("<<r.first<<" "<<r.second<<") with " <<"("<<io.first<<" "<<io.second<<")"<<endl;
             return false;
        }

    }
    return true;
}

bool contained(const pii& r , const vector<pii> IO){
     for(const auto io : IO){
        if( is_inside(r,io) || is_inside(io,r) )
           return true;
     }
           return false;
}
bool verify(vector<pii>& IO){

     for(const auto r : IO){

        if(!can_add(r,IO)){
            return false;
        }
    }
    return true;

}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

    I.push_back(*R.begin());
    D.insert(*R.begin());
    bool go = true;
    while(go){
        go=false;
        for(const auto r : R){
            if(D.find(r)!=D.end())
                continue;
            cerr<<endl<<r.first<<" " <<r.second<<" : ";
            if(!can_add(r,I)){
            cerr<<"adding to O";
                O.push_back(r);
                go=true;
                D.insert(r);
             }else if(!can_add(r,O)){
                cerr<<"adding to I";
                I.push_back(r);
                go=true;
                D.insert(r);
             }
        }
        if(go)
            continue;
         for(const auto r : R){
             if(D.find(r)!=D.end())
                continue;
             if(contained(r,I)){
                cerr<<"contained in I";
                I.push_back(r);
                go=true;
                D.insert(r);
                 break;
            }else if(contained(r,O)){
                cerr<<"contained in O";
                O.push_back(r);
                go=true;
                D.insert(r);
                 break;
            }
         }

    }
 if(verify(O) && verify(I))
    {
        for(const auto r : R){
            if(find(O.begin(), O.end(), r) != O.end())
                cout<<"o";
            else
                cout<<"i";
        }
        return 0;
    }

    cout<<"Impossible"<<endl;
    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;
void solve();

int n,m;
vector<pii> R,RO;
vector<pii> I,O;

bool intersect(const pii& r , const vector<pii> IO){
    for(const auto io : IO){
        if(r.first >= io.first && r.first < io.second)
            return true;
    }
    return false;
}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

    RO.resize(R.size());
    copy(R.begin(), R.end(), RO.begin()); //original order

    sort(begin(R), end(R));

    for(const auto r : R){
        if(!intersect(r,I)){
            I.push_back(r);
        }
        else if(pii r1(r.second,r.first) ; !intersect(r1,I)){
            I.push_back(r1);
        }
        else if(!intersect(r,O)){
            O.push_back(r);
        }
        else if(pii r2(r.second,r.first) ; !intersect(r2,O)){
            O.push_back(r1);
        }
        else
        {
            cout<<"Impossible"<<endl;
            return 0;
        }
    }
    for(const auto r : RO){
        if( find(I.begin(), I.end(), r) != I.end())
            cout<<"i";
        else
            cout<<"o";
    }

    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;
void solve();

int n,m;
vector<pii> R,RO;
vector<pii> I,O;

bool intersect(const pii& r , const vector<pii> IO){
    for(const auto io : IO){
        if(r.first >= io.first && r.first< io.second)
            return true;
    }
    return false;
}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

    RO.resize(R.size());
    copy(R.begin(), R.end(), RO.begin()); //original order

    sort(begin(R), end(R));

    for(const auto r : R){
        if(!intersect(r,I)){
            I.push_back(r);
        }
        else if(!intersect(r,O)){
            O.push_back(r);
        }
        else
        {
            cout<<"Impossible"<<endl;
            return 0;
        }
    }
    for(const auto r : RO){
        if( find(I.begin(), I.end(), r) != I.end())
            cout<<"i";
        else
            cout<<"o";
    }

    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;

int n,m;
vector<pii> R,RO;
vector<pii> I,O;

void print(vector<pii>& V){
 for(const auto p : V){
  cerr<<"("<<p.first<<" "<<p.second<<"), ";
 }
    cerr<<endl;
}

bool is_inside(const pii& r , const pii& r1){
  return
      r.first >= r1.first && r.second<=r1.second;
}

bool intersect(const pii& r , const pii& r1){
  return
      r.first > r1.first &&  r.first < r1.second && r.second > r1.second;
}

bool can_add(const pii& r , const vector<pii> IO){
    if(IO.size()<=0)
        return true;

    for(const auto io : IO){
        if(!( is_inside(r,io) || is_inside(io,r)  || (!intersect(r,io) && !intersect(io,r) ) )){
            //cerr<<"cannot add "<<"("<<r.first<<" "<<r.second<<") with " <<"("<<io.first<<" "<<io.second<<")"<<endl;
             return false;
        }

    }
    return true;
}

bool verify(vector<pii>& O){

     for(const auto r : O){

        if(!can_add(r,O)){
            return false;
        }
    }
    return true;

}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

     I.push_back(*R.begin());
     for(const auto r : R){

       /* cerr<<endl<<r.first<<" " <<r.second<<" : ";
        cerr<<"I: ";
        print(I);
        cerr<<"O: ";
        print(O);*/

        if(!can_add(r,I)){
            //cerr<<"i";
            O.push_back(r);
        }else if(!can_add(r,O)){
            I.push_back(r);
        }
    }
    if(verify(O) && verify(I))
    {
        for(const auto r : R){
            if(find(O.begin(), O.end(), r) != O.end())
                cout<<"o";
            else
                cout<<"i";
        }
        return 0;
    }

    cout<<"Impossible"<<endl;
    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;

int n,m;
vector<pii> R,RO;
vector<pii> I,O;
set<pii> D;

void print(vector<pii>& V){
 for(const auto p : V){
  cerr<<"("<<p.first<<" "<<p.second<<"), ";
 }
    cerr<<endl;
}

bool is_inside(const pii& r , const pii& r1){
  return
      r.first >= r1.first && r.second<=r1.second;
}

bool intersect(const pii& r , const pii& r1){
  return
      r.first > r1.first &&  r.first < r1.second && r.second > r1.second;
}

bool can_add(const pii& r , const vector<pii> IO){
    if(IO.size()<=0)
        return true;

    for(const auto io : IO){
        if(!( is_inside(r,io) || is_inside(io,r)  || (!intersect(r,io) && !intersect(io,r) ) )){
            cerr<<"cannot add "<<"("<<r.first<<" "<<r.second<<") with " <<"("<<io.first<<" "<<io.second<<")"<<endl;
             return false;
        }

    }
    return true;
}

bool verify(vector<pii>& IO){

     for(const auto r : IO){

        if(!can_add(r,IO)){
            return false;
        }
    }
    return true;

}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

    I.push_back(*R.begin());
    D.insert(*R.begin());
    bool go = true;
    while(go){
        go=false;
        for(const auto r : R){
            if(D.find(r)!=D.end())
                continue;
            cerr<<endl<<r.first<<" " <<r.second<<" : ";
            if(!can_add(r,I)){
            cerr<<"adding to O";
                O.push_back(r);
                go=true;
                D.insert(r);
             }else if(!can_add(r,O)){
                cerr<<"adding to I";
                I.push_back(r);
                go=true;
                D.insert(r);
             }
        }

    }
 if(verify(O) && verify(I))
    {
        for(const auto r : R){
            if(find(O.begin(), O.end(), r) != O.end())
                cout<<"o";
            else
                cout<<"i";
        }
        return 0;
    }

    cout<<"Impossible"<<endl;
    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;
void solve();

int n,m;
vector<pii> R,RO;
vector<pii> I,O;

bool intersect(const pii& r , const vector<pii> IO){
    for(const auto io : IO){
        if(r.first > io.first && r.first < io.second && r.second > io.second)
            return true;
    }
    return false;
}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

    RO.resize(R.size());
    copy(R.begin(), R.end(), RO.begin()); //original order

    sort(begin(R), end(R));

    for(const auto r : R){
        if(!intersect(r,I)){
            I.push_back(r);
        }
        else if(!intersect(r,O)){
            O.push_back(r);
        }
        else
        {
            cout<<"Impossible"<<endl;
            return 0;
        }
    }
    for(const auto r : RO){
        if(pii r1(r.second,r.first); find(I.begin(), I.end(), r) != I.end() || find(I.begin(), I.end(), r1) != I.end())
            cout<<"i";
        else
            cout<<"o";
    }

    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;
void solve();

int n,m;
vector<pii> R,RO;
vector<pii> I,O;

bool intersect(const pii& r , const vector<pii> IO){
    for(const auto io : IO){
        if((r.first > io.first && r.first < io.second && r.second > io.second) ||
          (io.first > r.first && io.first < r.second && io.second > r.second))
            return true;
    }
    return false;
}

bool solve(bool sorted){
    I.clear();
    O.clear();
    if(sorted)
       sort(begin(R), end(R));

     for(const auto r : R){
       // cerr<<r.first<<" " <<r.second<<endl;
        if(!intersect(r,I)){
          //  cerr<<" I " <<endl;;
            I.push_back(r);
        }
        else if(!intersect(r,O)){
           // cerr<<" O " <<endl;;
            O.push_back(r);
        }
        else
        {

            return false;
        }
    }
    return true;

}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

    RO.resize(R.size());
    copy(R.begin(), R.end(), RO.begin()); //original order

    //sort(begin(R), end(R));

    if(solve(false) || solve(true)){
        for(const auto r : RO){
            if(find(I.begin(), I.end(), r) != I.end())
                cout<<"i";
            else
                cout<<"o";
        }
    }else{
        cout<<"Impossible"<<endl;
          return 0;
    }

    return 0;
}


#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include <numeric>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace std::chrono;
using ull = unsigned long long;
using ul = unsigned long;
using pii = pair<int,int>;

int n,m;
vector<pii> R,RO;
vector<pii> I,O;

bool is_inside(const pii& r , const pii& r1){
  return
      r.first >= r1.first && r.second<=r1.second;
}

bool intersect(const pii& r , const pii& r1){
  return
      r.first > r1.first &&  r.first < r1.second && r.second > r1.second;
}

bool can_add(const pii& r , const vector<pii> IO){
    if(IO.size()<=0)
        return true;

    for(const auto io : IO){
        if(!( is_inside(r,io) || is_inside(io,r)  || (!intersect(r,io) && !intersect(io,r) ) ))
           return false;
    }
    return true;
}

bool solve(){

     for(const auto r : R){
       // cerr<<endl<<r.first<<" " <<r.second<<" : ";
        if(can_add(r,I)){
            //cerr<<"i";
            I.push_back(r);
        }
        else if(can_add(r,O)){
         //  cerr<<"o";
            O.push_back(r);
        }
        else
        {

             return false;
        }
    }
    return true;

}

int main() {
    cin>>n>>m;
    for(int i = 0 ; i < m ; i++){
        int a,b; cin>>a>>b;
        R.push_back(pii(min(a,b),max(a,b)));
    }

    if(solve())
    {
        for(const auto r : R){
            if(find(I.begin(), I.end(), r) != I.end())
                cout<<"i";
            else
                cout<<"o";
        }
        return 0;
    }

    cout<<"Impossible"<<endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
//#define int                 long long
#define ll                  long long
#define ld                  long double
#define rep(i,n)            for(int i=0;i<n;i++)
#define hell                1000000007
#define inf                 (ll)1e15
#define vi                  vector<int>
#define vii                 vector< vi >
#define pb                  push_back
#define mp                  make_pair
#define fi                  first
#define se                  second
#define pii                 pair<int,int>
#define all(c)              c.begin(),c.end()
#define sz(c)               (int)c.size()
#define hash1               105727LL
#define hash2               hell
#define eps                 1e-10
#define pi                  3.141592653589793238462643383279502884197
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
ll lcm(ll a, ll b) { return a * (b / gcd(a, b)); }
ll power(ll x, ll y,ll p)
{
	ll res=1;
	x=x%p;
	while(y>0)
	{
		if(y&1)
			res=((res%p)*(x%p))%p;
		y=y>>1;
		x=((x%p)*(x%p))%p;
	}
	return res;
}
ll raichu(ll x,ll y)
{
	ll res=1;
	while(y>0)
	{
		if(y&1)
			res=((res)*(x));
		y=y>>1;
		x=((x)*(x));
	}
	return res;
}
bool isprime(ll n)
{
	if(n<2) return false;
	else if(n==2) return true;
	else if(n%2==0) return false;
	else
	{
		ll z=sqrt(n);
		rep(i,z-1) if(n%(i+2)==0) return false;
		return true;
	}
}
bool dfs(int c,vii &g,vi &ans,int z)
{
	ans[c]=z;
	bool res=true;
	for(auto i:g[c])
	{
		if(ans[i]==-1) res&=dfs(i,g,ans,z^1);
		else if(ans[i]==z) return false;
		if(!res) return false;
	}
	return res;
}
int32_t main()
{
	//freopen("B-large.in","r",stdin);
	//freopen("out4.txt","w",stdout);
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int tests=1,Tests;
	//cin>>test;
	Tests=tests;
	while(tests--)
	{
		int n,m;
		cin>>n>>m;
		vector<pii> e(m);
		rep(i,m) cin>>e[i].fi>>e[i].se;
		rep(i,m) if(e[i].fi>e[i].se) swap(e[i].fi,e[i].se);
		vii g(m);
		rep(i,m)
		{
			for(int j=i+1;j<m;j++)
			{
				if(e[j].fi>=e[i].se || e[j].se<=e[i].fi || (e[j].fi>=e[i].fi && e[j].se<=e[i].se)) continue;
				else g[i].pb(j),g[j].pb(i);
			}
		}
		vi ans(m,-1);
		bool res=true;
		rep(i,m)
		{
			if(ans[i]==-1)
			{
				res&=dfs(i,g,ans,0);
				if(!res)
				{
					cout<<"Impossible";
					return 0;
				}
			}
		}
		rep(i,m)
		{
			if(ans[i]==0) cout<<'i';
			else cout<<'o';
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
//#define int                 long long
#define ll                  long long
#define ld                  long double
#define rep(i,n)            for(int i=0;i<n;i++)
#define hell                1000000007
#define inf                 (ll)1e15
#define vi                  vector<int>
#define vii                 vector< vi >
#define pb                  push_back
#define mp                  make_pair
#define fi                  first
#define se                  second
#define pii                 pair<int,int>
#define all(c)              c.begin(),c.end()
#define sz(c)               (int)c.size()
#define hash1               105727LL
#define hash2               hell
#define eps                 1e-10
#define pi                  3.141592653589793238462643383279502884197
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
ll lcm(ll a, ll b) { return a * (b / gcd(a, b)); }
ll power(ll x, ll y,ll p)
{
	ll res=1;
	x=x%p;
	while(y>0)
	{
		if(y&1)
			res=((res%p)*(x%p))%p;
		y=y>>1;
		x=((x%p)*(x%p))%p;
	}
	return res;
}
ll raichu(ll x,ll y)
{
	ll res=1;
	while(y>0)
	{
		if(y&1)
			res=((res)*(x));
		y=y>>1;
		x=((x)*(x));
	}
	return res;
}
bool isprime(ll n)
{
	if(n<2) return false;
	else if(n==2) return true;
	else if(n%2==0) return false;
	else
	{
		ll z=sqrt(n);
		rep(i,z-1) if(n%(i+2)==0) return false;
		return true;
	}
}
bool dfs(int c,vii &g,vi &ans,int z)
{
	ans[c]=z;
	bool res=true;
	for(auto i:g[c])
	{
		if(ans[i]==-1) res&=dfs(i,g,ans,z^1);
		else if(ans[i]==z) return false;
		if(!res) return false;
	}
	return res;
}
int32_t main()
{
	//freopen("B-large.in","r",stdin);
	//freopen("out4.txt","w",stdout);
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int tests=1,Tests;
	//cin>>test;
	Tests=tests;
	while(tests--)
	{
		int n,m;
		cin>>n>>m;
		vector<pii> e(m);
		rep(i,m) cin>>e[i].fi>>e[i].se;
		rep(i,m) if(e[i].fi>e[i].se) swap(e[i].fi,e[i].se);
		vii g(m);
		rep(i,m)
		{
			for(int j=i+1;j<m;j++)
			{
				if(e[j].fi>=e[i].se || e[j].se<=e[i].fi || (e[j].fi>=e[i].fi && e[j].se<=e[i].se) || (e[j].fi==e[i].fi) || (e[j].se==e[i].se)) continue;
				else g[i].pb(j),g[j].pb(i);
			}
		}
		vi ans(m,-1);
		bool res=true;
		rep(i,m)
		{
			if(ans[i]==-1)
			{
				res&=dfs(i,g,ans,0);
				if(!res)
				{
					cout<<"Impossible";
					return 0;
				}
			}
		}
		rep(i,m)
		{
			if(ans[i]==0) cout<<'i';
			else cout<<'o';
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
//#define int                 long long
#define ll                  long long
#define ld                  long double
#define rep(i,n)            for(int i=0;i<n;i++)
#define hell                1000000007
#define inf                 (ll)1e15
#define vi                  vector<int>
#define vii                 vector< vi >
#define pb                  push_back
#define mp                  make_pair
#define fi                  first
#define se                  second
#define pii                 pair<int,int>
#define all(c)              c.begin(),c.end()
#define sz(c)               (int)c.size()
#define hash1               105727LL
#define hash2               hell
#define eps                 1e-10
#define pi                  3.141592653589793238462643383279502884197
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
ll lcm(ll a, ll b) { return a * (b / gcd(a, b)); }
ll power(ll x, ll y,ll p)
{
	ll res=1;
	x=x%p;
	while(y>0)
	{
		if(y&1)
			res=((res%p)*(x%p))%p;
		y=y>>1;
		x=((x%p)*(x%p))%p;
	}
	return res;
}
ll raichu(ll x,ll y)
{
	ll res=1;
	while(y>0)
	{
		if(y&1)
			res=((res)*(x));
		y=y>>1;
		x=((x)*(x));
	}
	return res;
}
bool isprime(ll n)
{
	if(n<2) return false;
	else if(n==2) return true;
	else if(n%2==0) return false;
	else
	{
		ll z=sqrt(n);
		rep(i,z-1) if(n%(i+2)==0) return false;
		return true;
	}
}
bool dfs(int c,vii &g,vi &ans,int z)
{
	ans[c]=z;
	bool res=true;
	for(auto i:g[c])
	{
		if(ans[i]==-1) res&=dfs(i,g,ans,z^1);
		else if(ans[i]==z) return false;
		if(!res) return false;
	}
	return res;
}
int32_t main()
{
	//freopen("B-large.in","r",stdin);
	//freopen("out4.txt","w",stdout);
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int tests=1,Tests;
	//cin>>test;
	Tests=tests;
	while(tests--)
	{
		int n,m;
		cin>>n>>m;
		vector<pii> e(m);
		rep(i,m) cin>>e[i].fi>>e[i].se;
		rep(i,m) if(e[i].fi>e[i].se) swap(e[i].fi,e[i].se);
		vii g(m);
		rep(i,m)
		{
			for(int j=i+1;j<m;j++)
			{
				if(e[j].fi>=e[i].se || e[j].se<=e[i].fi || (e[j].fi>=e[i].fi && e[j].se<=e[i].se) || (e[j].fi==e[i].fi) || (e[j].se==e[i].se) || (e[i].fi>=e[j].fi && e[i].se<=e[j].se) || e[i].fi>=e[j].se || e[i].se<=e[j].fi) continue;
				else
				{
					//cout<<i<<" "<<j<<endl;
					g[i].pb(j),g[j].pb(i);
				}
			}
		}
		vi ans(m,-1);
		bool res=true;
		rep(i,m)
		{
			if(ans[i]==-1)
			{
				res&=dfs(i,g,ans,0);
				if(!res)
				{
					cout<<"Impossible";
					return 0;
				}
			}
		}
		rep(i,m)
		{
			if(ans[i]==0) cout<<'i';
			else cout<<'o';
		}
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define fz  first
#define sz second
const int N = 205;
vector<int> adj[2][N],topo;
vector<pii> vt;
int mark[N],ans[N];
int n,m,u,v,t,c;

void dfs_t(int u) {
	mark[u] = 1;
	for (auto v: adj[0][u])
		if (!mark[v])
			dfs_t(v);
	topo.push_back(u);
}

void dfs_c(int u) {
	mark[u] = c;
	for (auto v: adj[1][u])
		if (!mark[v])
			dfs_c(v);
}

void add_imp(int u,int v){
    adj[0][u^1].pb(v);
    adj[0][v^1].pb(u);

    adj[1][u].pb(v^1);
    adj[1][v].pb(u^1);
}

void add_xor(int u,int v){
    add_imp(u<<1,v<<1);
    add_imp(u<<1^1,v<<1^1);
}

bool safe(pii a,pii b,int p=0){
    if((a.fz<=b.fz && a.sz>=b.sz) || a.sz<=b.fz)
        return true;
    if(p)
        return false;
    return safe(b,a,p+1);
}

int main()
{
    cin>>n>>m;
    for(int i=0 ; i<m ; i++){
        cin>>u>>v;
        u--;v--;
        if(u>v)
            swap(u,v);
        vt.pb(mp(u,v));
    }

    for(int i=0 ; i<m ; i++){
        for(int j=i+1 ; j<m ; j++){
            if(!safe(vt[i],vt[j])){
                //cout<<vt[i].fz<<" "<<vt[i].sz<<"  and  "<<vt[j].fz<<" "<<vt[j].sz<<endl;
                add_xor(i,j);
            }
        }
    }

    for (int u = 0; u<2*m; u++)
		if (!mark[u])
			dfs_t(u);
	reverse(topo.begin(), topo.end());
	memset(mark,0,sizeof mark);

	for (auto u: topo)
		if (!mark[u]){
			c++;
			dfs_c(u);
		}

    for(int i=0 ; i<m ; i++){
	    if(mark[i<<1]==mark[i<<1^1]){
	        cout<<"Impossible";
	        return 0;
	    }else
	        ans[i]=(mark[i<<1]>mark[i<<1^1]);
	}

	for(int i=0 ; i<m ; i++)
	    if(ans[i])
	        cout<<"i";
	    else
	        cout<<"o";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define fz  first
#define sz second
const int N = 205;
vector<int> adj[2][N],topo;
vector<pii> vt;
int mark[N],ans[N];
int n,m,u,v,t,c;

void dfs_t(int u) {
	mark[u] = 1;
	for (auto v: adj[0][u])
		if (!mark[v])
			dfs_t(v);
	topo.push_back(u);
}

void dfs_c(int u) {
	mark[u] = c;
	for (auto v: adj[1][u])
		if (!mark[v])
			dfs_c(v);
}

void add_imp(int u,int v){
    adj[0][u^1].pb(v);
    adj[0][v^1].pb(u);

    adj[1][u].pb(v^1);
    adj[1][v].pb(u^1);
}

void add_xor(int u,int v){
    add_imp(u<<1,v<<1);
    add_imp(u<<1^1,v<<1^1);
}

bool safe(pii a,pii b,int p=0){
    if(a.fz<=b.fz && a.sz>=b.sz)
        return true;
    if(p)
        return false;
    return safe(b,a,p+1);
}

int main()
{
    cin>>n>>m;
    for(int i=0 ; i<m ; i++){
        cin>>u>>v;
        u--;v--;
        if(u>v)
            swap(u,v);
        vt.pb(mp(u,v));
    }

    for(int i=0 ; i<m ; i++){
        for(int j=i+1 ; j<m ; j++){
            if(!safe(vt[i],vt[j])){
                add_xor(i,j);
            }
        }
    }

    for (int u = 0; u<2*m; u++)
		if (!mark[u])
			dfs_t(u);
	reverse(topo.begin(), topo.end());
	memset(mark,0,sizeof mark);

	for (auto u: topo)
		if (!mark[u]){
			c++;
			dfs_c(u);
		}

    for(int i=0 ; i<m ; i++){
	    if(mark[i<<1]==mark[i<<1^1]){
	        cout<<"Impossible";
	        return 0;
	    }else
	        ans[i]=(mark[i<<1]>mark[i<<1^1]);
	}

	for(int i=0 ; i<m ; i++)
	    if(ans[i])
	        cout<<"i";
	    else
	        cout<<"o";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define fz  first
#define sz second
const int N = 205;
vector<int> adj[2][N],topo;
vector<pii> vt;
int mark[N],ans[N];
int n,m,u,v,t,c;

void dfs_t(int u) {
	mark[u] = 1;
	for (auto v: adj[0][u])
		if (!mark[v])
			dfs_t(v);
	topo.push_back(u);
}

void dfs_c(int u) {
	mark[u] = c;
	for (auto v: adj[1][u])
		if (!mark[v])
			dfs_c(v);
}

void add_imp(int u,int v){
    adj[0][u^1].pb(v);
    adj[0][v^1].pb(u);

    adj[1][u].pb(v^1);
    adj[1][v].pb(u^1);
}

void add_xor(int u,int v){
    add_imp(u<<1,v<<1);
    add_imp(u<<1^1,v<<1^1);
}

bool safe(pii a,pii b,int p=0){
    if(a.fz<=b.fz && a.sz>=b.sz)
        return true;
    if(p)
        return false;
    return safe(b,a,p+1);
}

int main()
{
    cin>>n>>m;
    for(int i=0 ; i<m ; i++){
        cin>>u>>v;
        u--;v--;
        vt.pb(mp(u,v));
    }

    for(int i=0 ; i<m ; i++){
        for(int j=i+1 ; j<m ; j++){
            if(!safe(vt[i],vt[j])){
                add_xor(i,j);
            }
        }
    }

    for (int u = 0; u<2*m; u++)
		if (!mark[u])
			dfs_t(u);
	reverse(topo.begin(), topo.end());
	memset(mark,0,sizeof mark);

	for (auto u: topo)
		if (!mark[u]){
			c++;
			dfs_c(u);
		}

    for(int i=0 ; i<m ; i++){
	    if(mark[i<<1]==mark[i<<1^1]){
	        cout<<"Impossible";
	        return 0;
	    }else
	        ans[i]=(mark[i<<1]>mark[i<<1^1]);
	}

	for(int i=0 ; i<m ; i++)
	    if(ans[i])
	        cout<<"i";
	    else
	        cout<<"o";
    return 0;
}


#include <algorithm>
#include <iomanip>
#include <istream>
#include <map>
#include <numeric>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <functional>

#define V vector
#define pb push_back

#include <math.h>

using namespace std;

class Solution {
public:
	bool areInt(V<int>& r1, V<int>& r2){
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (r1[i] == r2[j]) return false;
			}
		}

		sort(r2.begin(), r2.end());
		int cnt = 0;
		for (int i = 0; i < 2; i++) {
			if (r1[i] > r2[0] && r1[i] < r2[1]) {
				cnt++;
			}
		}
		return cnt == 1;
	}
	V<int> order;
	V<int> used;
	void dfsOrd(int v) {
		if (used[v])return;
		used[v] = true;
		for (auto ch : G[v]) {
			dfsOrd(ch);
		}
		order.pb(v);
	}
	void dfs(int v, int c) {
		if (used[v] != -1) return;
		used[v] = c;
		for (auto ch : G[v]) {
			dfs(ch, c);
		}
	}
	V<V<int>> G, tG;
    void solve(int num, std::istream& in, std::ostream& out) {
		int n, m; in>>n>>m;
		vector<V<int>> arr;
		for(int i = 0;i < m;i++) {
			int x, y; in >> x >> y;
			x--, y--;
			arr.pb({ x, y });
		}
		int N = 2 * m;
		G.resize(N); tG.resize(N);
		used.resize(N);
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			for (int j = i + 1; j < m; j++) {
				int y = 2 * j;
				if (areInt(arr[i], arr[j])) {
					G[x].pb(y + 1);
					G[y].pb(x + 1);
					G[x + 1].pb(y);
					G[y + 1].pb(x);
				}
			}
		}
		for (int i = 0; i < N; i++) for (auto j : G[i]) tG[j].pb(i);

		for (int i = 0; i < N; i++) {
			if (used[i]) continue;
			dfsOrd(i);
		}
		used.assign(N, -1);
		int c = 0;

		for (int i = 0; i < N; i++) {
			int v = order[i];// order[N - 1 - i];
			if (used[v] != -1) continue;
			dfs(v, c);
			c++;
		}
		string rez = "";
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			if (used[x] == used[x + 1]) {
				out << "Impossible" << endl; return;
			}
			rez += used[x] < used[x + 1] ? 'o' : 'i';
		}

		out << rez;
    }
};

void solve(std::istream& in, std::ostream& out)
{
    out << std::setprecision(12);
    Solution solution;
	//int T; in >> T;
	//for(int i = 0;i < T;i++)
		//solution.solve(i+1, in, out);
	solution.solve(0, in, out);
}

#include <fstream>
#include <iostream>

int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    istream& in = cin;

    ostream& out = cout;

    solve(in, out);
    return 0;
}


#include <algorithm>
#include <iomanip>
#include <istream>
#include <map>
#include <numeric>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <functional>

#define V vector
#define pb push_back

#include <math.h>

using namespace std;

class Solution {
public:
	bool areInt(V<int>& r1, V<int>& r2){
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (r1[i] == r2[j]) return false;
			}
		}

		sort(r2.begin(), r2.end());
		int cnt = 0;
		for (int i = 0; i < 2; i++) {
			if (r1[i] > r2[0] && r1[i] < r2[1]) {
				cnt++;
			}
		}
		return cnt == 1;
	}
	V<int> order;
	V<int> used;
	void dfsOrd(int v) {
		if (used[v])return;
		used[v] = true;
		for (auto ch : G[v]) {
			dfsOrd(ch);
		}
		order.pb(v);
	}
	void dfs(int v, int c) {
		if (used[v] != -1) return;
		used[v] = c;
		for (auto ch : G[v]) {
			dfs(v, c);
		}
	}
	V<V<int>> G;
    void solve(int num, std::istream& in, std::ostream& out) {
		int n, m; in>>n>>m;
		vector<V<int>> arr;
		for(int i = 0;i < m;i++) {
			int x, y; in >> x >> y;
			x--, y--;
			arr.pb({ x, y });
		}
		int N = 2 * m;
		G.resize(N);
		used.resize(N);
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			for (int j = i + 1; j < m; j++) {
				int y = 2 * j;
				if (areInt(arr[i], arr[j])) {
					G[x].pb(y + 1);
					G[y].pb(x + 1);
					G[x + 1].pb(y);
					G[y + 1].pb(x);
				}
			}
		}

		for (int i = 0; i < N; i++) {
			if (used[i]) continue;
			dfsOrd(i);
		}
		used.assign(N, -1);
		int c = 0;
		for (int i = 0; i < N; i++) {
			int v = order[i];
			if (used[v] != -1) continue;
			dfs(v, c);
			c++;
		}
		string rez = "";
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			if (used[x] == used[x + 1]) {
				out << "Impossible" << endl; return;
			}
			rez += used[x] < used[x + 1] ? 'o' : 'i';
		}

		out << rez;
    }
};

void solve(std::istream& in, std::ostream& out)
{
    out << std::setprecision(12);
    Solution solution;
	//int T; in >> T;
	//for(int i = 0;i < T;i++)
		//solution.solve(i+1, in, out);
	solution.solve(0, in, out);
}

#include <fstream>
#include <iostream>

int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    istream& in = cin;

    ostream& out = cout;

    solve(in, out);
    return 0;
}


#include <algorithm>
#include <iomanip>
#include <istream>
#include <map>
#include <numeric>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <functional>

#define V vector
#define pb push_back

#include <math.h>

using namespace std;

class Solution {
public:
	bool areInt(V<int>& r1, V<int>& r2){
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (r1[i] == r2[j]) return false;
			}
		}

		sort(r2.begin(), r2.end());
		int cnt = 0;
		for (int i = 0; i < 2; i++) {
			if (r1[i] > r2[0] && r1[i] < r2[1]) {
				cnt++;
			}
		}
		return cnt == 1;
	}
	V<int> order;
	V<int> used;
	void dfsOrd(int v) {
		if (used[v])return;
		used[v] = true;
		for (auto ch : G[v]) {
			dfsOrd(ch);
		}
		order.pb(v);
	}
	void dfs(int v, int c) {
		if (used[v] != -1) return;
		used[v] = c;
		for (auto ch : tG[v]) {
			dfs(ch, c);
		}
	}
	V<V<int>> G, tG;
    void solve(int num, std::istream& in, std::ostream& out) {
		int n, m; in>>n>>m;
		vector<V<int>> arr;
		for(int i = 0;i < m;i++) {
			int x, y; in >> x >> y;
			x--, y--;
			arr.pb({ x, y });
		}
		int N = 2 * m;
		G.resize(N); tG.resize(N);
		used.resize(N);
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			for (int j = i + 1; j < m; j++) {
				int y = 2 * j;
				if (areInt(arr[i], arr[j])) {
					G[x].pb(y + 1);
					G[y].pb(x + 1);
					G[x + 1].pb(y);
					G[y + 1].pb(x);
				}
			}
		}
		for (int i = 0; i < N; i++) for (auto j : G[i]) tG[j].pb(i);

		for (int i = 0; i < N; i++) {
			if (used[i]) continue;
			dfsOrd(i);
		}
		used.assign(N, -1);
		int c = 0;

		for (int i = 0; i < N; i++) {
			int v = order[N - 1 - i];
			if (used[v] != -1) continue;
			dfs(v, c);
			c++;
		}
		string rez = "";
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			if (used[x] == used[x + 1]) {
				out << "Impossible" << endl; return;
			}
			rez += used[x] < used[x + 1] ? 'o' : 'i';
		}

		out << rez;
    }
};

void solve(std::istream& in, std::ostream& out)
{
    out << std::setprecision(12);
    Solution solution;
	//int T; in >> T;
	//for(int i = 0;i < T;i++)
		//solution.solve(i+1, in, out);
	solution.solve(0, in, out);
}

#include <fstream>
#include <iostream>

int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    istream& in = cin;

    ostream& out = cout;

    solve(in, out);
    return 0;
}


#include <algorithm>
#include <iomanip>
#include <istream>
#include <map>
#include <numeric>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <functional>

#define V vector
#define pb push_back

#include <math.h>

using namespace std;

class Solution {
public:
	bool areInt(V<int>& r1, V<int>& r2){
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (r1[i] == r2[j]) return false;
			}
		}

		sort(r2.begin(), r2.end());
		int cnt = 0;
		for (int i = 0; i < 2; i++) {
			if (r1[i] > r2[0] && r1[i] < r2[1]) {
				cnt++;
			}
		}
		return cnt == 1;
	}
	V<int> order;
	V<int> used;
	void dfsOrd(int v) {
		if (used[v])return;
		used[v] = true;
		for (auto ch : G[v]) {
			dfsOrd(ch);
		}
		order.pb(v);
	}
	void dfs(int v, int c) {
		if (used[v] != -1) return;
		used[v] = c;
		for (auto ch : G[v]) {
			dfs(v, c);
		}
	}
	V<V<int>> G;
    void solve(int num, std::istream& in, std::ostream& out) {
		int n, m; in>>n>>m;
		vector<V<int>> arr;
		for(int i = 0;i < m;i++) {
			int x, y; in >> x >> y;
			x--, y--;
			arr.pb({ x, y });
		}
		int N = 2 * m;
		G.resize(N);
		used.resize(N);
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			for (int j = i + 1; j < m; j++) {
				int y = 2 * j;
				if (areInt(arr[i], arr[j])) {
					G[x].pb(y + 1);
					G[y].pb(x + 1);
					G[x + 1].pb(y);
					G[y + 1].pb(x);
				}
			}
		}

		for (int i = 0; i < N; i++) {
			if (used[i]) continue;
			dfsOrd(i);
		}
		used.assign(N, -1);
		int c = 0;

		for (int i = 0; i < N; i++) {
			int v = order[N - 1 - i];
			if (used[v] != -1) continue ;
			dfs(v, c);
			c++;
		}
		string rez = "";
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			if (used[x] == used[x + 1]) {
				out << "Impossible" << endl; return;
			}
			rez += used[x] < used[x + 1] ? 'o' : 'i';
		}

		out << rez;
    }
};

void solve(std::istream& in, std::ostream& out)
{
    out << std::setprecision(12);
    Solution solution;
	//int T; in >> T;
	//for(int i = 0;i < T;i++)
		//solution.solve(i+1, in, out);
	solution.solve(0, in, out);
}

#include <fstream>
#include <iostream>

int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    istream& in = cin;

    ostream& out = cout;

    solve(in, out);
    return 0;
}


#include <algorithm>
#include <iomanip>
#include <istream>
#include <map>
#include <numeric>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <functional>

#define V vector
#define pb push_back

#include <math.h>

using namespace std;

class Solution {
public:
	bool areInt(V<int>& r1, V<int>& r2){
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (r1[i] == r2[j]) return false;
			}
		}

		sort(r2.begin(), r2.end());
		int cnt = 0;
		for (int i = 0; i < 2; i++) {
			if (r1[i] > r2[0] && r1[i] < r2[1]) {
				cnt++;
			}
		}
		return cnt == 1;
	}
	V<int> order;
	V<int> used;
	void dfsOrd(int v) {
		if (used[v])return;
		used[v] = true;
		for (auto ch : G[v]) {
			dfsOrd(ch);
		}
		order.pb(v);
	}
	void dfs(int v, int c) {
		if (used[v] != -1) return;
		used[v] = c;
		for (auto ch : tG[v]) {
			dfs(v, c);
		}
	}
	V<V<int>> G, tG;
    void solve(int num, std::istream& in, std::ostream& out) {
		int n, m; in>>n>>m;
		vector<V<int>> arr;
		for(int i = 0;i < m;i++) {
			int x, y; in >> x >> y;
			x--, y--;
			arr.pb({ x, y });
		}
		int N = 2 * m;
		G.resize(N); tG.resize(N);
		used.resize(N);
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			for (int j = i + 1; j < m; j++) {
				int y = 2 * j;
				if (areInt(arr[i], arr[j])) {
					G[x].pb(y + 1);
					G[y].pb(x + 1);
					G[x + 1].pb(y);
					G[y + 1].pb(x);
				}
			}
		}
		for (int i = 0; i < N; i++) for (auto j : G[i]) tG[j].pb(i);

		for (int i = 0; i < N; i++) {
			if (used[i]) continue;
			dfsOrd(i);
		}
		used.assign(N, -1);
		int c = 0;

		for (int i = 0; i < N; i++) {
			int v = order[N - 1 - i];
			if (used[v] != -1) continue;
			dfs(v, c);
			c++;
		}
		string rez = "";
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			if (used[x] == used[x + 1]) {
				out << "Impossible" << endl; return;
			}
			rez += used[x] < used[x + 1] ? 'o' : 'i';
		}

		out << rez;
    }
};

void solve(std::istream& in, std::ostream& out)
{
    out << std::setprecision(12);
    Solution solution;
	//int T; in >> T;
	//for(int i = 0;i < T;i++)
		//solution.solve(i+1, in, out);
	solution.solve(0, in, out);
}

#include <fstream>
#include <iostream>

int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    istream& in = cin;

    ostream& out = cout;

    solve(in, out);
    return 0;
}


#include <algorithm>
#include <iomanip>
#include <istream>
#include <map>
#include <numeric>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <functional>

#define V vector
#define pb push_back

#include <math.h>

using namespace std;

class Solution {
public:
	bool areInt(V<int>& r1, V<int>& r2){
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (r1[i] == r2[j]) return false;
			}
		}

		sort(r2.begin(), r2.end());
		int cnt = 0;
		for (int i = 0; i < 2; i++) {
			if (r1[i] > r2[0] && r1[i] < r2[1]) {
				cnt++;
			}
		}
		return cnt == 1;
	}
	V<int> order;
	V<int> used;
	void dfsOrd(int v) {
		if (used[v])return;
		used[v] = true;
		for (auto ch : G[v]) {
			dfsOrd(ch);
		}
		order.pb(v);
	}
	void dfs(int v, int c) {
		if (used[v] != -1) return;
		used[v] = c;
		for (auto ch : G[v]) {
			dfs(v, c);
		}
	}
	V<V<int>> G;
    void solve(int num, std::istream& in, std::ostream& out) {
		int n, m; in>>n>>m;
		vector<V<int>> arr;
		for(int i = 0;i < m;i++) {
			int x, y; in >> x >> y;
			x--, y--;
			arr.pb({ x, y });
		}
		int N = 2 * m;
		G.resize(N);
		used.resize(N);
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			for (int j = i + 1; j < m; j++) {
				int y = 2 * j;
				if (areInt(arr[i], arr[j])) {
					G[x].pb(y + 1);
					G[y].pb(x + 1);
					G[x + 1].pb(y);
					G[y + 1].pb(x);
				}
			}
		}

		for (int i = 0; i < N; i++) {
			if (used[i]) continue;
			dfsOrd(i);
		}
		used.assign(N, -1);
		int c = 0;
		for (int i = 0; i < N; i++) {
			int v = order[i];
			if (used[v] != -1) continue ;
			dfs(v, c);
			c++;
		}
		string rez = "";
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			if (used[x] == used[x + 1]) {
				out << "Impossible" << endl; return;
			}
			rez += used[x] < used[x + 1] ? 'o' : 'i';
		}

		out << rez;
    }
};

void solve(std::istream& in, std::ostream& out)
{
    out << std::setprecision(12);
    Solution solution;
	//int T; in >> T;
	//for(int i = 0;i < T;i++)
		//solution.solve(i+1, in, out);
	solution.solve(0, in, out);
}

#include <fstream>
#include <iostream>

int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    istream& in = cin;

    ostream& out = cout;

    solve(in, out);
    return 0;
}


#include <algorithm>
#include <iomanip>
#include <istream>
#include <map>
#include <numeric>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <functional>

#define V vector
#define pb push_back

#include <math.h>

using namespace std;

class Solution {
public:
	bool areInt(V<int>& r1, V<int>& r2){
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (r1[i] == r2[j]) return false;
			}
		}

		sort(r2.begin(), r2.end());
		int cnt = 0;
		for (int i = 0; i < 2; i++) {
			if (r1[i] > r2[0] && r1[i] < r2[1]) {
				cnt++;
			}
		}
		return cnt == 1;
	}
	V<int> order;
	V<int> used;
	void dfsOrd(int v) {
		if (used[v])return;
		used[v] = true;
		for (auto ch : G[v]) {
			dfsOrd(ch);
		}
		order.pb(v);
	}
	void dfs(int v, int c) {
		if (used[v] != -1) return;
		used[v] = c;
		for (auto ch : tG[v]) {
			dfs(v, c);
		}
	}
	V<V<int>> G, tG;
    void solve(int num, std::istream& in, std::ostream& out) {
		int n, m; in>>n>>m;
		vector<V<int>> arr;
		for(int i = 0;i < m;i++) {
			int x, y; in >> x >> y;
			x--, y--;
			arr.pb({ x, y });
		}
		int N = 2 * m;
		G.resize(N); tG.resize(N);
		used.resize(N);
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			for (int j = i + 1; j < m; j++) {
				int y = 2 * j;
				if (areInt(arr[i], arr[j])) {
					G[x].pb(y + 1);
					G[y].pb(x + 1);
					G[x + 1].pb(y);
					G[y + 1].pb(x);
				}
			}
		}
		for (int i = 0; i < N; i++) for (auto j : G[i]) tG[j].pb(i);

		for (int i = 0; i < N; i++) {
			if (used[i]) continue;
			dfsOrd(i);
		}
		used.assign(N, -1);
		int c = 0;

		for (int i = 0; i < N; i++) {
			int v = order[N - 1 - i];
			if (used[v] != -1) continue ;
			dfs(v, c);
			c++;
		}
		string rez = "";
		for (int i = 0; i < m; i++) {
			int x = 2 * i;
			if (used[x] == used[x + 1]) {
				out << "Impossible" << endl; return;
			}
			rez += used[x] < used[x + 1] ? 'o' : 'i';
		}

		out << rez;
    }
};

void solve(std::istream& in, std::ostream& out)
{
    out << std::setprecision(12);
    Solution solution;
	//int T; in >> T;
	//for(int i = 0;i < T;i++)
		//solution.solve(i+1, in, out);
	solution.solve(0, in, out);
}

#include <fstream>
#include <iostream>

int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    istream& in = cin;

    ostream& out = cout;

    solve(in, out);
    return 0;
}


#include<bits/stdc++.h>

using namespace std;
using i64 = long long;
using i32 = int;

template<typename T> T load() { T x; cin >> x; return x; }
template<typename T> vector<T> loadN(int s) { vector<T> vt(s); for(auto& el : vt) el = load<T>(); return vt; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& vt) { for(auto& el : vt) os << el << ' '; return os; }

struct Graph {
    Graph(int s):edges(s) {}
    struct dummy { template<typename ... Ts> void operator()(Ts&& ...) {} };
    void addEdge(int i, int j) { edges[i].push_back(j); }
    void addBiEdge(i32 i, i32 j) { addEdge(i, j); addEdge(j, i); }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void allDfs(PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        auto vis = vector<bool>(size());
        for(i32 i = 0 ; i < size() ; ++i)
            if(not vis[i])
                implDfs(i, vis, prev, pree, poste, faile, postv);
    }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void implDfs(int v, vector<bool>& vis, PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        vis[v] = true;
        prev(v);
        for(auto& to : edges[v]) {
            if(not vis[to])
                pree(v, to), implDfs(to, vis, prev, pree, poste, faile, postv), poste(v,to);
            else
                faile(v, to);
        }
        postv(v);
    }
    template<typename F>
    void tarjan(F f) {
        auto graphSize = size();
        auto ord = vector<i32>(graphSize, -1);
        auto low = vector<i32>(graphSize, -1);
        auto onStack = vector<bool>(graphSize);
        auto S = vector<i32>();
        auto timer = -1;
        allDfs(
            [&](i32 v) { low[v] = ord[v] = ++timer; onStack[v] = true; S.push_back(v); },
            {},
            [&](i32 f, i32 t) { low[f] = min(low[f], low[t]); },
            [&](i32 f, i32 t) { if(onStack[t]) low[f] = min(low[f], ord[t]); },
            [&](i32 v) {
                if(low[v] != ord[v]) return;
                auto popped = -1;
                auto f2 = f();
                do {
                    popped = S.back(); S.pop_back();
                    onStack[popped] = false;
                    f2(popped);
                } while(popped != v);
            }
        );
    }

    int size() { return edges.size(); }
    vector<vector<int>> edges;
};

struct SatSolution {
    bool isValid() const { return solution.size() > 0; }
    bool operator[](i32 idx) const { return solution[idx]; }
    vector<bool> solution;
};

struct SatBuilder {
    SatBuilder(i32 size):relationships(2 * size), size(size) {}
    void addExpression(i32 i, i32 j) { relationships.addEdge(neg(i), j); relationships.addEdge(neg(j), i); }
    void addRelation(i32 i, i32 j) { relationships.addEdge(i, j); }
    i32 neg(i32 val) const { return val + (val >= size ? -size : + size); }
    SatSolution solve() {
        auto sccCounter = -1;
        auto inScc = vector<i32>(2 * size, -1);
        relationships.tarjan([&](){
            ++sccCounter;
            return [&](i32 v) {
                inScc[v] = sccCounter;
            };
        });
        for(i32 i = 0 ; i < size ; ++i)
            if(inScc[i] == inScc[i + size])
                return SatSolution{vector<bool>()};

        auto solution = vector<bool>(size);

        for(i32 i = 0 ; i < size ; ++i)
            solution[i] = inScc[i] < inScc[i + size];
        return SatSolution{ move(solution) };
    }
    Graph relationships;
    i32 size;
};

struct Edge {
    i32 i, j;
};
template<> Edge load() { Edge x; x.i = load<i32>() - 1; x.j = load<i32>() - 1; if(x.i > x.j) swap(x.i, x.j); return x; }

bool collides(Edge foo, Edge bar) {
    if(foo.i > bar.i)
        swap(foo, bar);
    return foo.i < bar.i && bar.i < foo.j && foo.j < bar.j;
}

int main() {
    ios::sync_with_stdio(false);
    auto ringSize = load<i32>();
    auto edgeNum = load<i32>();
    auto edges = loadN<Edge>(edgeNum);
    auto sat = SatBuilder(edgeNum);
    for(i32 i = 0 ; i < edgeNum ; ++i) {
        for(i32 j = i + 1 ; j < edgeNum ; ++j) {
            if(collides(edges[i], edges[j])) {
                sat.addExpression(i, j);
                sat.addExpression(sat.neg(i), sat.neg(j));
            }
        }
    }

    auto sol = sat.solve();
    if(sol.isValid()) {
        for(i32 i = 0 ; i < edgeNum ; ++i)
            cout << (sol[i] ? 'i' : 'o');
        cout << '\n';
    }
    else {
        //final warning
        cout << "Impossible\n";
    }

}


#include<bits/stdc++.h>

using namespace std;
using i64 = long long;
using i32 = int;

template<typename T> T load() { T x; cin >> x; return x; }
template<typename T> vector<T> loadN(int s) { vector<T> vt(s); for(auto& el : vt) el = load<T>(); return vt; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& vt) { for(auto& el : vt) os << el << ' '; return os; }

struct Graph {
    Graph(int s):edges(s) {}
    struct dummy { template<typename ... Ts> void operator()(Ts&& ...) {} };
    void addEdge(int i, int j) { edges[i].push_back(j); }
    void addBiEdge(i32 i, i32 j) { addEdge(i, j); addEdge(j, i); }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void allDfs(PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        auto vis = vector<bool>(size());
        for(i32 i = 0 ; i < size() ; ++i)
            if(not vis[i])
                implDfs(i, vis, prev, pree, poste, faile, postv);
    }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void implDfs(int v, vector<bool>& vis, PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        vis[v] = true;
        prev(v);
        for(auto& to : edges[v]) {
            if(not vis[to])
                pree(v, to), implDfs(to, vis, prev, pree, poste, faile, postv), poste(v,to);
            else
                faile(v, to);
        }
        postv(v);
    }
    template<typename F>
    void tarjan(F f) {
        auto graphSize = size();
        auto ord = vector<i32>(graphSize, -1);
        auto low = vector<i32>(graphSize, -1);
        auto onStack = vector<bool>(graphSize);
        auto S = vector<i32>();
        auto timer = -1;
        allDfs(
            [&](i32 v) { low[v] = ord[v] = ++timer; onStack[v] = true; S.push_back(v); },
            {},
            [&](i32 f, i32 t) { low[f] = min(low[f], low[t]); },
            [&](i32 f, i32 t) { if(onStack[t]) low[f] = min(low[f], ord[t]); },
            [&](i32 v) {
                if(low[v] != ord[v]) return;
                auto popped = -1;
                auto f2 = f();
                do {
                    popped = S.back(); S.pop_back();
                    onStack[popped] = false;
                    f2(popped);
                } while(popped != v);
            }
        );
    }

    int size() { return edges.size(); }
    vector<vector<int>> edges;
};

struct SatSolution {
    bool isValid() const { return solution.size() > 0; }
    bool operator[](i32 idx) const { return solution[idx]; }
    vector<bool> solution;
};

struct SatBuilder {
    SatBuilder(i32 size):relationships(2 * size), size(size) {}
    void addExpression(i32 i, i32 j) { relationships.addEdge(neg(i), j); relationships.addEdge(neg(j), i); }
    void addRelation(i32 i, i32 j) { relationships.addEdge(i, j); }
    i32 neg(i32 val) const { return val + (val >= size ? -size : + size); }
    SatSolution solve() {
        auto sccCounter = -1;
        auto inScc = vector<i32>(2 * size, -1);
        relationships.tarjan([&](){
            ++sccCounter;
            return [&](i32 v) {
                inScc[v] = sccCounter;
            };
        });
        for(i32 i = 0 ; i < size ; ++i)
            if(inScc[i] == inScc[i + size])
                return SatSolution{vector<bool>()};

        auto solution = vector<bool>(size);

        for(i32 i = 0 ; i < size ; ++i)
            solution[i] = inScc[i] < inScc[i + size];
        return SatSolution{ move(solution) };
    }
    Graph relationships;
    i32 size;
};

struct Edge {
    i32 i, j;
};
template<> Edge load() { Edge x; x.i = load<i32>() - 1; x.j = load<i32>() - 1; if(x.i > x.j) swap(x.i, x.j); return x; }

bool collides(Edge foo, Edge bar) {
    if(foo.i > bar.i)
        swap(foo, bar);
    return foo.i < bar.i && bar.i < foo.j && foo.j < bar.j;
}

int main() {
    ios::sync_with_stdio(false);
    auto ringSize = load<i32>();
    auto edgeNum = load<i32>();
    auto edges = loadN<Edge>(edgeNum);
    auto sat = SatBuilder(edgeNum);
    for(i32 i = 0 ; i < edgeNum ; ++i) {
        for(i32 j = i + 1 ; j < edgeNum ; ++j) {
            if(collides(edges[i], edges[j])) {
                sat.addExpression(i, j);
                sat.addExpression(sat.neg(i), sat.neg(j));
            }
        }
    }

    auto sol = sat.solve();
    if(sol.isValid()) {
        for(i32 i = 0 ; i < edgeNum ; ++i)
            cout << (sol[i] ? 'i' : 'o');
        cout << '\n';
    }
    else {
        //koty
        //psy
        //jaszczur
        cout << "Impossible\n";
    }

}


#include<bits/stdc++.h>

using namespace std;
using i64 = long long;
using i32 = int;

template<typename T> T load() { T x; cin >> x; return x; }
template<typename T> vector<T> loadN(int s) { vector<T> vt(s); for(auto& el : vt) el = load<T>(); return vt; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& vt) { for(auto& el : vt) os << el << ' '; return os; }

struct Graph {
    Graph(int s):edges(s) {}
    struct dummy { template<typename ... Ts> void operator()(Ts&& ...) {} };
    void addEdge(int i, int j) { edges[i].push_back(j); }
    void addBiEdge(i32 i, i32 j) { addEdge(i, j); addEdge(j, i); }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void allDfs(PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        auto vis = vector<bool>(size());
        for(i32 i = 0 ; i < size() ; ++i)
            if(not vis[i])
                implDfs(i, vis, prev, pree, poste, faile, postv);
    }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void implDfs(int v, vector<bool>& vis, PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        vis[v] = true;
        prev(v);
        for(auto& to : edges[v]) {
            if(not vis[to])
                pree(v, to), implDfs(to, vis, prev, pree, poste, faile, postv), poste(v,to);
            else
                faile(v, to);
        }
        postv(v);
    }
    template<typename F>
    void tarjan(F f) {
        auto graphSize = size();
        auto ord = vector<i32>(graphSize, -1);
        auto low = vector<i32>(graphSize, -1);
        auto onStack = vector<bool>(graphSize);
        auto S = vector<i32>();
        auto timer = -1;
        allDfs(
            [&](i32 v) { low[v] = ord[v] = ++timer; onStack[v] = true; S.push_back(v); },
            {},
            [&](i32 f, i32 t) { low[f] = min(low[f], low[t]); },
            [&](i32 f, i32 t) { if(onStack[t]) low[f] = min(low[f], ord[t]); },
            [&](i32 v) {
                if(low[v] != ord[v]) return;
                auto popped = -1;
                auto f2 = f();
                do {
                    popped = S.back(); S.pop_back();
                    onStack[popped] = false;
                    f2(popped);
                } while(popped != v);
            }
        );
    }

    int size() { return edges.size(); }
    vector<vector<int>> edges;
};

struct SatSolution {
    bool isValid() const { return solution.size() > 0; }
    bool operator[](i32 idx) const { return solution[idx]; }
    vector<bool> solution;
};

struct SatBuilder {
    SatBuilder(i32 size):relationships(2 * size), size(size) {}
    void addExpression(i32 i, i32 j) { relationships.addEdge(neg(i), j); relationships.addEdge(neg(j), i); }
    void addRelation(i32 i, i32 j) { relationships.addEdge(i, j); }
    i32 neg(i32 val) const { return val + (val >= size ? -size : + size); }
    SatSolution solve() {
        auto sccCounter = -1;
        auto inScc = vector<i32>(2 * size, -1);
        relationships.tarjan([&](){
            ++sccCounter;
            return [&](i32 v) {
                inScc[v] = sccCounter;
            };
        });
        for(i32 i = 0 ; i < size ; ++i)
            if(inScc[i] == inScc[i + size])
                return SatSolution{vector<bool>()};

        auto solution = vector<bool>(size);

        for(i32 i = 0 ; i < size ; ++i)
            solution[i] = inScc[i] < inScc[i + size];
        return SatSolution{ move(solution) };
    }
    Graph relationships;
    i32 size;
};

struct Edge {
    i32 i, j;
};
template<> Edge load() { Edge x; x.i = load<i32>() - 1; x.j = load<i32>() - 1; if(x.i > x.j) swap(x.i, x.j); return x; }

bool collides(Edge foo, Edge bar) {
    if(foo.i > bar.i)
        swap(foo, bar);
    return foo.i < bar.i && bar.i < foo.j && foo.j < bar.j;
}

int main() {
    ios::sync_with_stdio(false);
    auto ringSize = load<i32>();
    auto edgeNum = load<i32>();
    auto edges = loadN<Edge>(edgeNum);
    auto sat = SatBuilder(edgeNum);
    for(i32 i = 0 ; i < edgeNum ; ++i) {
        for(i32 j = i + 1 ; j < edgeNum ; ++j) {
            if(collides(edges[i], edges[j])) {
                sat.addExpression(i, j);
                sat.addExpression(sat.neg(i), sat.neg(j));
            }
        }
    }

    auto sol = sat.solve();
    if(sol.isValid()) {
        for(i32 i = 0 ; i < edgeNum ; ++i)
            cout << (sol[i] ? 'i' : 'o');
        cout << '\n';
    }
    else {
        //final warningsss
        cout << "Impossible\n";
    }

}


#include<bits/stdc++.h>

using namespace std;
using i64 = long long;
using i32 = int;

template<typename T> T load() { T x; cin >> x; return x; }
template<typename T> vector<T> loadN(int s) { vector<T> vt(s); for(auto& el : vt) el = load<T>(); return vt; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& vt) { for(auto& el : vt) os << el << ' '; return os; }

struct Graph {
    Graph(int s):edges(s) {}
    struct dummy { template<typename ... Ts> void operator()(Ts&& ...) {} };
    void addEdge(int i, int j) { edges[i].push_back(j); }
    void addBiEdge(i32 i, i32 j) { addEdge(i, j); addEdge(j, i); }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void allDfs(PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        auto vis = vector<bool>(size());
        for(i32 i = 0 ; i < size() ; ++i)
            if(not vis[i])
                implDfs(i, vis, prev, pree, poste, faile, postv);
    }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void implDfs(int v, vector<bool>& vis, PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        vis[v] = true;
        prev(v);
        for(auto& to : edges[v]) {
            if(not vis[to])
                pree(v, to), implDfs(to, vis, prev, pree, poste, faile, postv), poste(v,to);
            else
                faile(v, to);
        }
        postv(v);
    }
    template<typename F>
    void tarjan(F f) {
        auto graphSize = size();
        auto ord = vector<i32>(graphSize, -1);
        auto low = vector<i32>(graphSize, -1);
        auto onStack = vector<bool>(graphSize);
        auto S = vector<i32>();
        auto timer = -1;
        allDfs(
            [&](i32 v) { low[v] = ord[v] = ++timer; onStack[v] = true; S.push_back(v); },
            {},
            [&](i32 f, i32 t) { low[f] = min(low[f], low[t]); },
            [&](i32 f, i32 t) { if(onStack[t]) low[f] = min(low[f], ord[t]); },
            [&](i32 v) {
                if(low[v] != ord[v]) return;
                auto popped = -1;
                auto f2 = f();
                do {
                    popped = S.back(); S.pop_back();
                    onStack[popped] = false;
                    f2(popped);
                } while(popped != v);
            }
        );
    }

    int size() { return edges.size(); }
    vector<vector<int>> edges;
};

struct SatSolution {
    bool isValid() const { return solution.size() > 0; }
    bool operator[](i32 idx) const { return solution[idx]; }
    vector<bool> solution;
};

struct SatBuilder {
    SatBuilder(i32 size):relationships(2 * size), size(size) {}
    void addExpression(i32 i, i32 j) { relationships.addEdge(neg(i), j); relationships.addEdge(neg(j), i); }
    void addRelation(i32 i, i32 j) { relationships.addEdge(i, j); }
    i32 neg(i32 val) const { return val + (val >= size ? -size : + size); }
    SatSolution solve() {
        auto sccCounter = -1;
        auto inScc = vector<i32>(2 * size, -1);
        relationships.tarjan([&](){
            ++sccCounter;
            return [&](i32 v) {
                inScc[v] = sccCounter;
            };
        });
        for(i32 i = 0 ; i < size ; ++i)
            if(inScc[i] == inScc[i + size])
                return SatSolution{vector<bool>()};

        auto solution = vector<bool>(size);

        for(i32 i = 0 ; i < size ; ++i)
            solution[i] = inScc[i] < inScc[i + size];
        return SatSolution{ move(solution) };
    }
    Graph relationships;
    i32 size;
};

struct Edge {
    i32 i, j;
};
template<> Edge load() { Edge x; x.i = load<i32>() - 1; x.j = load<i32>() - 1; if(x.i > x.j) swap(x.i, x.j); return x; }

bool collides(Edge foo, Edge bar) {
    if(foo.i > bar.i)
        swap(foo, bar);
    return foo.i < bar.i && bar.i < foo.j && foo.j < bar.j;
}

int main() {
    ios::sync_with_stdio(false);
    auto ringSize = load<i32>();
    auto edgeNum = load<i32>();
    auto edges = loadN<Edge>(edgeNum);
    auto sat = SatBuilder(edgeNum);
    for(i32 i = 0 ; i < edgeNum ; ++i) {
        for(i32 j = i + 1 ; j < edgeNum ; ++j) {
            if(collides(edges[i], edges[j])) {
                sat.addExpression(i, j);
                sat.addExpression(sat.neg(i), sat.neg(j));
            }
        }
    }

    auto sol = sat.solve();
    if(sol.isValid()) {
        for(i32 i = 0 ; i < edgeNum ; ++i)
            cout << (sol[i] ? 'i' : 'o');
        cout << '\n';
    }
    else {
        //koty
        cout << "Impossible\n";
    }

}


#include<bits/stdc++.h>

using namespace std;
using i64 = long long;
using i32 = int;

template<typename T> T load() { T x; cin >> x; return x; }
template<typename T> vector<T> loadN(int s) { vector<T> vt(s); for(auto& el : vt) el = load<T>(); return vt; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& vt) { for(auto& el : vt) os << el << ' '; return os; }

struct Graph {
    Graph(int s):edges(s) {}
    struct dummy { template<typename ... Ts> void operator()(Ts&& ...) {} };
    void addEdge(int i, int j) { edges[i].push_back(j); }
    void addBiEdge(i32 i, i32 j) { addEdge(i, j); addEdge(j, i); }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void allDfs(PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        auto vis = vector<bool>(size());
        for(i32 i = 0 ; i < size() ; ++i)
            if(not vis[i])
                implDfs(i, vis, prev, pree, poste, faile, postv);
    }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void implDfs(int v, vector<bool>& vis, PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        vis[v] = true;
        prev(v);
        for(auto& to : edges[v]) {
            if(not vis[to])
                pree(v, to), implDfs(to, vis, prev, pree, poste, faile, postv), poste(v,to);
            else
                faile(v, to);
        }
        postv(v);
    }
    template<typename F>
    void tarjan(F f) {
        auto graphSize = size();
        auto ord = vector<i32>(graphSize, -1);
        auto low = vector<i32>(graphSize, -1);
        auto onStack = vector<bool>(graphSize);
        auto S = vector<i32>();
        auto timer = -1;
        allDfs(
            [&](i32 v) { low[v] = ord[v] = ++timer; onStack[v] = true; S.push_back(v); },
            {},
            [&](i32 f, i32 t) { low[f] = min(low[f], low[t]); },
            [&](i32 f, i32 t) { if(onStack[t]) low[f] = min(low[f], ord[t]); },
            [&](i32 v) {
                if(low[v] != ord[v]) return;
                auto popped = -1;
                auto f2 = f();
                do {
                    popped = S.back(); S.pop_back();
                    onStack[popped] = false;
                    f2(popped);
                } while(popped != v);
            }
        );
    }

    int size() { return edges.size(); }
    vector<vector<int>> edges;
};

struct SatSolution {
    bool isValid() const { return solution.size() > 0; }
    bool operator[](i32 idx) const { return solution[idx]; }
    vector<bool> solution;
};

struct SatBuilder {
    SatBuilder(i32 size):relationships(2 * size), size(size) {}
    void addExpression(i32 i, i32 j) { relationships.addEdge(neg(i), j); relationships.addEdge(neg(j), i); }
    void addRelation(i32 i, i32 j) { relationships.addEdge(i, j); }
    i32 neg(i32 val) const { return val + (val >= size ? -size : + size); }
    SatSolution solve() {
        auto sccCounter = -1;
        auto inScc = vector<i32>(2 * size, -1);
        relationships.tarjan([&](){
            ++sccCounter;
            return [&](i32 v) {
                inScc[v] = sccCounter;
            };
        });
        for(i32 i = 0 ; i < size ; ++i)
            if(inScc[i] == inScc[i + size])
                return SatSolution{vector<bool>()};

        auto solution = vector<bool>(size);

        for(i32 i = 0 ; i < size ; ++i)
            solution[i] = inScc[i] < inScc[i + size];
        return SatSolution{ move(solution) };
    }
    Graph relationships;
    i32 size;
};

struct Edge {
    i32 i, j;
};
template<> Edge load() { Edge x; x.i = load<i32>() - 1; x.j = load<i32>() - 1; if(x.i > x.j) swap(x.i, x.j); return x; }

bool collides(Edge foo, Edge bar) {
    if(foo.i > bar.i)
        swap(foo, bar);
    return foo.i < bar.i && bar.i < foo.j && foo.j < bar.j;
}

int main() {
    ios::sync_with_stdio(false);
    auto ringSize = load<i32>();
    auto edgeNum = load<i32>();
    auto edges = loadN<Edge>(edgeNum);
    auto sat = SatBuilder(edgeNum);
    for(i32 i = 0 ; i < edgeNum ; ++i) {
        for(i32 j = i + 1 ; j < edgeNum ; ++j) {
            if(collides(edges[i], edges[j])) {
                sat.addExpression(i, j);
                sat.addExpression(sat.neg(i), sat.neg(j));
            }
        }
    }

    auto sol = sat.solve();
    if(sol.isValid()) {
        for(i32 i = 0 ; i < edgeNum ; ++i)
            cout << (sol[i] ? 'i' : 'o');
        cout << '\n';
    }
    else {
        //koty
        //psy
        cout << "Impossible\n";
    }

}


#include<bits/stdc++.h>

using namespace std;
using i64 = long long;
using i32 = int;

template<typename T> T load() { T x; cin >> x; return x; }
template<typename T> vector<T> loadN(int s) { vector<T> vt(s); for(auto& el : vt) el = load<T>(); return vt; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& vt) { for(auto& el : vt) os << el << ' '; return os; }

struct Graph {
    Graph(int s):edges(s) {}
    struct dummy { template<typename ... Ts> void operator()(Ts&& ...) {} };
    void addEdge(int i, int j) { edges[i].push_back(j); }
    void addBiEdge(i32 i, i32 j) { addEdge(i, j); addEdge(j, i); }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void allDfs(PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        auto vis = vector<bool>(size());
        for(i32 i = 0 ; i < size() ; ++i)
            if(not vis[i])
                implDfs(i, vis, prev, pree, poste, faile, postv);
    }
    template<typename PreV = dummy, typename PreE = dummy, typename PostE = dummy, typename FailE = dummy, typename PostV = dummy>
    void implDfs(int v, vector<bool>& vis, PreV prev, PreE pree, PostE poste, FailE faile, PostV postv) {
        vis[v] = true;
        prev(v);
        for(auto& to : edges[v]) {
            if(not vis[to])
                pree(v, to), implDfs(to, vis, prev, pree, poste, faile, postv), poste(v,to);
            else
                faile(v, to);
        }
        postv(v);
    }
    template<typename F>
    void tarjan(F f) {
        auto graphSize = size();
        auto ord = vector<i32>(graphSize, -1);
        auto low = vector<i32>(graphSize, -1);
        auto onStack = vector<bool>(graphSize);
        auto S = vector<i32>();
        auto timer = -1;
        allDfs(
            [&](i32 v) { low[v] = ord[v] = ++timer; onStack[v] = true; S.push_back(v); },
            {},
            [&](i32 f, i32 t) { low[f] = min(low[f], low[t]); },
            [&](i32 f, i32 t) { if(onStack[t]) low[f] = min(low[f], ord[t]); },
            [&](i32 v) {
                if(low[v] != ord[v]) return;
                auto popped = -1;
                auto f2 = f();
                do {
                    popped = S.back(); S.pop_back();
                    onStack[popped] = false;
                    f2(popped);
                } while(popped != v);
            }
        );
    }

    int size() { return edges.size(); }
    vector<vector<int>> edges;
};

struct SatSolution {
    bool isValid() const { return solution.size() > 0; }
    bool operator[](i32 idx) const { return solution[idx]; }
    vector<bool> solution;
};

struct SatBuilder {
    SatBuilder(i32 size):relationships(2 * size), size(size) {}
    void addExpression(i32 i, i32 j) { relationships.addEdge(neg(i), j); relationships.addEdge(neg(j), i); }
    void addRelation(i32 i, i32 j) { relationships.addEdge(i, j); }
    i32 neg(i32 val) const { return val + (val >= size ? -size : + size); }
    SatSolution solve() {
        auto sccCounter = -1;
        auto inScc = vector<i32>(2 * size, -1);
        relationships.tarjan([&](){
            ++sccCounter;
            return [&](i32 v) {
                inScc[v] = sccCounter;
            };
        });
        for(i32 i = 0 ; i < size ; ++i)
            if(inScc[i] == inScc[i + size])
                return SatSolution{vector<bool>()};

        auto solution = vector<bool>(size);

        for(i32 i = 0 ; i < size ; ++i)
            solution[i] = inScc[i] < inScc[i + size];
        return SatSolution{ move(solution) };
    }
    Graph relationships;
    i32 size;
};

struct Edge {
    i32 i, j;
};
template<> Edge load() { Edge x; x.i = load<i32>() - 1; x.j = load<i32>() - 1; if(x.i > x.j) swap(x.i, x.j); return x; }

bool collides(Edge foo, Edge bar) {
    if(foo.i > bar.i)
        swap(foo, bar);
    return foo.i < bar.i && bar.i < foo.j && foo.j < bar.j;
}

int main() {
    ios::sync_with_stdio(false);
    auto ringSize = load<i32>();
    auto edgeNum = load<i32>();
    auto edges = loadN<Edge>(edgeNum);
    auto sat = SatBuilder(edgeNum);
    for(i32 i = 0 ; i < edgeNum ; ++i) {
        for(i32 j = i + 1 ; j < edgeNum ; ++j) {
            if(collides(edges[i], edges[j])) {
                sat.addExpression(i, j);
                sat.addExpression(sat.neg(i), sat.neg(j));
            }
        }
    }

    auto sol = sat.solve();
    if(sol.isValid()) {
        for(i32 i = 0 ; i < edgeNum ; ++i)
            cout << (sol[i] ? 'i' : 'o');
        cout << '\n';
    }
    else {
        //dsadasdasdasd
        //koty
        //psy
        //jaszczur
        cout << "Impossible\n";
    }

}