var s:String = readLine()!
let q:Int = Int(readLine()!)!
var c1:Int = 1
var s1:String = ""
var s2:String = ""
for _ in 0..<q {
  let query = readLine()!
  if query.contains(" ") {
    let l = query.split(separator:" ")
    let c2 = (l[1] == "1" ? 1:-1)
    if c1*c2 == 1 {
      s1 += l[2]
    } else {
      s2 += l[2]
    }
  } else {
    c1 = -c1
  }
}
s = String(s1.reversed()) + s + s2
print(c1 == 1 ? s:String(s.reversed()))


import Foundation

func readWords<T>(_ f: (Substring) -> T) -> [T] {
    return readLine()!.split(separator: " ").map(f)
}

func main() {
    let s = readLine()!.map { String($0) }
    let q = Int(readLine()!)!

    var deque = Deque<String>()
    for c in s {
        deque.pushBack(c)
    }

    var origin = true
    for _ in 1...q {
        let query = readWords { String($0) }
        if query[0] == "1" {
            origin = !origin
        } else {
            if query[1] == "1" {
                if origin {
                    deque.pushFront(query[2])
                } else {
                    deque.pushBack(query[2])
                }
            } else {
                if origin {
                    deque.pushBack(query[2])
                } else {
                    deque.pushFront(query[2])
                }
            }
        }
    }

    var ans = [String]()
    while let c = origin ? deque.popFront() : deque.popBack() {
        ans.append(c)
    }

    print(ans.joined(separator: ""))
}

private struct Deque<T> {
    public var buffer: [T?]
    private var head: Int
    private var tail: Int

    init() {
        buffer = [T?](repeating: nil, count: 8)
        head = 0
        tail = 0
    }

    public var isEmpty: Bool {
        return tail == head
    }

    public var capacity: Int {
        return buffer.count
    }

    public var count: Int {
        return (head &- tail) & (capacity - 1)
    }

    public var isFull: Bool {
        return capacity - count == 1
    }

    private func wrapIndex(index: Int, size: Int) -> Int {
        return index & (size - 1)
    }

    private func wrapAdd(index: Int, append: Int) -> Int {
        return wrapIndex(index: index &+ append, size: capacity)
    }

    private func wrapSub(index: Int, subtrahend: Int) -> Int {
        return wrapIndex(index: index &- subtrahend, size: capacity)
    }

    mutating func growIfNecessary() {
        if isFull {
            let oldCap = capacity
            buffer.append(contentsOf: Array(repeating: nil, count: oldCap))
            handleCapacityIncrease(oldCap: oldCap)
        }
    }

    private mutating func handleCapacityIncrease(oldCap: Int) {
        let newCap = capacity

        //  T      H
        // [ooooooo.]
        //  T      H
        // [ooooooo.........]
        if tail <= head {
            // nop
        }
        //    HT
        // [oo.ooooo]
        //     T      H
        // [...ooooooo......]
        else if head < oldCap - tail {
            buffer.withUnsafeMutableBufferPointer { buf in
                let base = buf.baseAddress!
                for i in 0...head {
                    swap(&base[i], &base[i+oldCap])
                }
            }
            head += oldCap
        }
        //       HT
        // [ooooo.oo]
        //       H        T
        // [ooooo.........oo]
        else {
            let newTail = newCap - (oldCap - tail)
            buffer.withUnsafeMutableBufferPointer { buf in
                let base = buf.baseAddress!
                for i in tail..<oldCap {
                    swap(&base[i], &base[i-tail+newTail])
                }
            }
            tail = newTail
        }
    }

    public mutating func pushBack(_ element: T) {
        growIfNecessary()

        let head = self.head
        self.head = wrapAdd(index: self.head, append: 1)
        buffer[head] = element
    }

    public mutating func pushFront(_ element: T) {
        growIfNecessary()

        self.tail = wrapSub(index: self.tail, subtrahend: 1)
        let tail = self.tail
        buffer[tail] = element
    }

    mutating func popBack() -> T? {
        if isEmpty {
            return nil
        } else {
            self.head = wrapSub(index: self.head, subtrahend: 1)
            let head = self.head
            return buffer[head]
        }
    }

    mutating func popFront() -> T? {
        if isEmpty {
            return nil
        } else {
            let tail = self.tail
            self.tail = wrapAdd(index: self.tail, append: 1)
            return buffer[tail]
        }
    }

    func peekFront() -> T? {
        if isEmpty {
            return nil
        } else {
            return buffer[head]
        }
    }

    func peekBack() -> T? {
        if isEmpty {
            return nil
        } else {
            return buffer[tail]
        }
    }
}

main()


s = input()
q = int(input())
s1 = ""
s2 = ""
c = 1
for i in range(q):
  a = input()
  if " " in a:
    l = list(a.split())
    c2 = 3-2*int(l[1])
    if c*c2 == 1:
      s1 = s1 + l[2]
    else:
      s2 = s2 + l[2]
  else:
    c = -c
s = s1[::-1] + s + s2
if c == 1:
  print(s)
else:
  print(s[::-1])


var s:String = readLine()!
let q:Int = Int(readLine()!)!
var c1:Int = 1
var s1:String = ""
var s2:String = ""
for _ in 0..<q {
  let query = readLine()!
  if query.contains(" ") {
    let l = query.split(separator:" ")
    let c2 = (l[1] == "1" ? 1:-1)
    if c1*c2 == 1 {
      s1 = l[2] + s1
    } else {
      s2 += l[2]
    }
  } else {
    c1 = -c1
  }
}
s = s1 + s + s2
print(c1 == 1 ? s:String(s.reversed()))


var s:String = readLine()!
let q:Int = Int(readLine()!)!
var c1:Int = 1
for _ in 0..<q {
  let query = readLine()!
  if query.contains(" ") {
    let l = query.split(separator:" ")
    let c2 = (l[1] == "1" ? 1:-1)
    if c1*c2 == 1 {
      s = l[2] + s
    } else {
      s += l[2]
    }
  } else {
    c1 = -c1
  }
}
print(c1 == 1 ? s:String(s.reversed()))


import * as fs from "fs";

interface FlipQuery {
	type: "flip";
}

interface AddQuery {
	type: "add";
	to: "start" | "end";
	char: string
}

type Query = FlipQuery | AddQuery;

const input = (fs.readFileSync("/dev/stdin", "utf8") as string).split("\n");
const s = input[0];
const q = +input[1];
const queries = [];
for (let i = 0; i < q; i++) {
	const query = input[i + 2].split(" ");
	if (query[0] === "1") {
		queries.push({ type: "flip" });
	} else {
		if (query[1] === "1") {
			queries.push({ type: "add", to: "start", char: query[2] });
		} else {
			queries.push({ type: "add", to: "end", char: query[2] });
		}
	}
}
queries.reverse()
let strs: [string, string] = ["", ""];
let flip_count = 0;

for (const query of queries) {
	if (query.type === "flip") {
		flip_count++;
		continue;
	}
	else if (query.type === "add") {
		// add
		const to = (query as AddQuery).to;
		const char = (query as AddQuery).char;
		const reversed = flip_count % 2 === 1;

		let to_start = to === "start";
		if (reversed) to_start = !to_start;
		strs[to_start ? 0 : 1] += char;
	}
}

let result = strs[0];
if (flip_count % 2 === 1) {
	result += s.split("").reverse().join("");
} else {
	result += s;
}
result += strs[1].split("").reverse().join("");

console.log(result);


function main(input) {
  const inputs =input.split('\n')
  const [S] = inputs[0].split(' ')
  const [Qn] = inputs[1].split(' ').map(Number)
  const Q = inputs.slice(2).map(e => {
    const q = e.split(' ')
    return {
      id: q[0],
      f: q[1],
      c: q[2]
    }
  })
  // console.log(Q)
  // console.log(S)
  let s = S
  let rev = 0
  for(let i = 0; i < Qn; i++) {
    if (Q[i].id === '1') {
      rev++
    } else {
      if (Q[i].f === '1' ^ rev % 2 === 0) {
        s = s + Q[i].c
      } else {
        s = Q[i].c + s
      }
    }
  }
  if (rev % 2 === 1) s = s.split('').reverse().join('')
  console.log(s)
}

main(require('fs').readFileSync('/dev/stdin', 'utf8'))


function main(input) {
  const inputs =input.split('\n')
  const [S] = inputs[0].split(' ')
  const [Qn] = inputs[1].split(' ').map(Number)
  const Q = inputs.slice(2).map(e => {
    const q = e.split(' ')
    return {
      id: q[0],
      f: q[1],
      c: q[2]
    }
  })
  // console.log(Q)
  // console.log(S)
  let s = S
  for(let i = 0; i < Qn; i++) {
    if (Q[i].id === '1') {
      s = s.split('').reverse().join('')
    } else {
      if (Q[i].f === '1') {
        s = Q[i].c + s
      } else {
        s = s + Q[i].c
      }
    }
  }
  console.log(s)
}

main(require('fs').readFileSync('/dev/stdin', 'utf8'))


import * as fs from "fs";

interface FlipQuery {
	type: "flip";
}

interface AddQuery {
	type: "add";
	to: "start" | "end";
	char: string
}

type Query = FlipQuery | AddQuery;

const input = (fs.readFileSync("/dev/stdin", "utf8") as string).split("\n");
const s = input[0];
const q = +input[1];
const queries = [];
for (let i = 0; i < q; i++) {
	const query = input[i + 2].split(" ");
	if (query[0] === "1") {
		queries.push({ type: "flip" });
	} else {
		if (query[1] === "1") {
			queries.push({ type: "add", to: "start", char: query[2] });
		} else {
			queries.push({ type: "add", to: "end", char: query[2] });
		}
	}
}
queries.reverse()
let strs: [string, string] = ["", ""];
let flip_count = 0;

for (const query of queries) {
	if (query.type === "flip") {
		flip_count++;
		continue;
	}
	else if (query.type === "add") {
		// add
		const to = (query as AddQuery).to;
		const char = (query as AddQuery).char;
		const reversed = flip_count % 2 === 1;

		let to_start = to === "start";
		if (reversed) to_start = !to_start;
		strs[to_start ? 0 : 1] += char;
	}
}

let result = strs[0];
if (flip_count % 2 === 1) {
	result += [...s].reverse().join("");
} else {
	result += s;
}
result += [...strs[1]].reverse().join("");

console.log(result);


import * as fs from "fs";

interface FlipQuery {
	type: "flip";
}

interface AddQuery {
	type: "add";
	to: "start" | "end";
	char: string
}

type Query = FlipQuery | AddQuery;

const input = (fs.readFileSync("/dev/stdin", "utf8") as string).split("\n");
const s = input[0];
const q = +input[1];
const queries = [];
for (let i = 0; i < q; i++) {
	const query = input[i + 2].split(" ");
	if (query[0] === "1") {
		queries.push({ type: "flip" });
	} else {
		if (query[1] === "1") {
			queries.push({ type: "add", to: "start", char: query[2] });
		} else {
			queries.push({ type: "add", to: "end", char: query[2] });
		}
	}
}
queries.reverse()
let strs: [string, string] = ["", ""];
let flip_count = 0;

for (const query of queries) {
	if (query.type === "flip") {
		flip_count++;
		continue;
	}
	else if (query.type === "add") {
		// add
		const { to, char } = query as AddQuery;
		const reversed = flip_count % 2 === 1;

		let to_start = to === "start";
		if (reversed) to_start = !to_start;
		strs[to_start ? 0 : 1] += char;
	}
}

let result = strs[0];
if (flip_count % 2 === 1) {
	result += [...s].reverse().join("");
} else {
	result += s;
}
result += [...strs[1]].reverse().join("");

console.log(result);


N = input()
if N[-1] in ["2", "4","5","7","9"]:
    print("hon")
elif N[-1] in ["0","1","6","8"]:
    print("pon")
else:
    print("bon")


N = int(input())

N1 = N - int(N/10)*10

yomi = 'hon'

if N1 == 3:
    yomi = 'bon'
elif N1 == 0 or N1 == 1 or N1 == 6 or N1 == 8:
    yomi = 'pon'

print(yomi)


n = input()
if n[-1] == "2" or n[-1] == "4" or n[-1] == "5" or n[-1] == "7" or n[-1] == "9":
    print("hon")
elif n[-1] == "3":
    print("bon")
else:
    print("pon")


n = int(input())
if n == 3:
    print("bon")
elif n in [0, 1, 6, 8]:
    print("pon")
else:
    print("hon")


n = int(input())
if n == 3:
    print('bon')
elif n in [0, 1, 6, 8]:
    print('pon')
else:
    print('hon')


n=int(input()[-1])
if n==3:
    res="bon"
elif n in [0,1,6,8]:
    res="pon"
else:
    res="bon"
print(res)


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String args[]) throws IOException{
        process();
    }
    public static void process() throws IOException{
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(in.readLine());
        int k=n%10;
        if(k==2 || k==4 || k==5 || k==7 || k==9)
            System.out.println("hon");
        else if(k==3)
            System.out.println("bon");
        else
            System.out.println("pon");
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;

class Main {

	public static void main(String[] args) {
		final FastScanner sc = new FastScanner(System.in);
		int n = sc.nextInt();
		switch (n % 10) {
			case 2:
			case 4:
			case 5:
			case 7:
			case 9:
				System.out.println("hon");
				break;
			case 0:
			case 1:
			case 6:
			case 8:
				System.out.println("pon");
				break;
			case 3:
				System.out.println("bon");
		}
	}

	static class FastScanner {
		private final InputStream in;
		private final byte[] buffer = new byte[1024];
		private int ptr = 0;
		private int buflen = 0;

		public FastScanner(InputStream source) {
			in = source;
		}

		private boolean hasNextByte() {
			if (ptr < buflen) {
				return true;
			} else {
				ptr = 0;
				try {
					buflen = in.read(buffer);
				} catch (IOException e) {
					e.printStackTrace();
				}
				if (buflen <= 0) {
					return false;
				}
			}
			return true;
		}

		private int readByte() {
			if (hasNextByte()) return buffer[ptr++];
			else return -1;
		}

		private static boolean isPrintableChar(int c) {
			return 33 <= c && c <= 126;
		}

		public boolean hasNext() {
			while (hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;
			return hasNextByte();
		}

		public String next() {
			if (!hasNext()) throw new NoSuchElementException();
			StringBuilder sb = new StringBuilder();
			int b = readByte();
			while (isPrintableChar(b)) {
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		public long nextLong() {
			if (!hasNext()) throw new NoSuchElementException();
			long n = 0;
			boolean minus = false;
			int b = readByte();
			if (b == '-') {
				minus = true;
				b = readByte();
			}
			if (b < '0' || '9' < b) {
				throw new NumberFormatException();
			}
			while (true) {
				if ('0' <= b && b <= '9') {
					n *= 10;
					n += b - '0';
				} else if (b == -1 || !isPrintableChar(b)) {
					return minus ? -n : n;
				} else {
					throw new NumberFormatException();
				}
				b = readByte();
			}
		}

		public int nextInt() {
			long nl = nextLong();
			if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE)
				throw new NumberFormatException();
			return (int) nl;
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}
	}
}


import java.util.*;
import java.io.*;
public class Main {

	public static void main(String[] args) throws Exception{
		int num = 998244353;

		// TODO Auto-generated method stub
 		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
 		PrintWriter out = new PrintWriter(System.out);
 		int n = Integer.parseInt(bf.readLine());
 		int k = n%10;
 		if (k == 3)
 			out.println("bon");
 		else if (k == 0 || k == 1 || k == 6 || k == 8)
 			out.println("pon");
 		else
 			out.println("hon");
 		out.close();

 	}
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String number = in.nextLine();

        int lastIndex = number.length() - 1;
        char lastChar = number.charAt(lastIndex);

        String ans = "";
        if (lastChar == 2 || lastChar == 4 || lastChar == 5 || lastChar == 7 || lastChar == 9) {
            ans = "hon";
        } else if (lastChar == 0 || lastChar == 1 || lastChar == 6 || lastChar == 8) {
            ans = "pon";
        } else  {
            ans = "bon";
        }
        System.out.println(ans);
    }
}


import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();

        switch (N) {
            case 2:
            case 4:
            case 5:
            case 7:
            case 9:
                System.out.println("hon");
                break;
            case 0:
            case 1:
            case 6:
            case 8:
                System.out.println("pon");
                break;
            case 3:
                System.out.println("bon");
        }
    }
}


import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();

        switch (n) {
            case 2:
            case 4:
            case 5:
            case 7:
            case 9:
                System.out.println("hon");
                break;
            case 0:
            case 1:
            case 6:
            case 8:
                System.out.println("pon");
                break;
            case 3:
                System.out.println("bon");
        }
    }
}


#include<cstdio>
using namespace std;
int main()
{
	int N, c;
	scanf("%d", &N);

		c=N%10;

	if(c==3) printf("bon");
	if(c==2||c==4||c==5||c==7||c==9) printf("hon");
	if(c==0||c==1||c==6||c==8) printf("pon");
	return 0;
 }


#include <stdio.h>

int main(void) {

    int N; /*入力*/

    scanf("%d", &N);

    N = N % 10; /*1の位*/

    if (N == 2 || N == 4 || N == 5 || N == 7 || N == 9) {
        printf("hon");
    }else if (N == 0 || N == 1 || N == 6 || N == 8) {
        printf("pon");
    }else{
        printf("bon");
    };

    return 0;
}


#include <cstdio>

int main() {
  int n;
  scanf("%d", &n);
  int k = n % 10;
  if(k == 3) {
    puts("bon");
  } else if(k == 0 || k == 1 || k == 6 || k == 8) {
    puts("pon");
  } else {
    puts("hon");
  }
  return 0;
}


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

int main(){
    float a,b,h,m, x;
    scanf("%f%f%f%f",&a,&b,&h,&m);
    float y=m/2;
    if (h*5>=m){
        x=((h*5)-m)*6+y;
    }
    else{
        x=(m-(h*5))*6+y;
    }
    float ans=sqrt((a*a)+(b*b)-(2*a*b*cos(x* M_PI /180.0)));
    cout<<setprecision(20)<<fixed;
    cout<<ans;
}
// 9899901000000100


#include<bits/stdc++.h>
using namespace std;
using ll=long long int;
ll mod=1e9+7;
ll power(ll a,ll b)
{
    ll result=1;
    while(b>0)
    {
        if(b%2==1)
        {
            result=(result*a)%mod;
        }
        b/=2;
        a=(a*a)%mod;
    }
    return result;
}
int main()
{

    vector<ll> powe(3e5,0);
    powe[0]=1;
    for(int i=1;i<3e5;i++)
    {
        powe[i]=(powe[i-1]*2)%mod;
    }
    int n;
    cin>>n;
    vector<pair<ll,ll> > a(n);
    map<pair<ll,ll>,int> m;
    for(int i=0;i<n;i++)
    {
        cin>>a[i].first>>a[i].second;

        ll p=__gcd(a[i].first,a[i].second);
        a[i].first/=p;
        a[i].second/=p;
         if(a[i].first>0&&a[i].second<0)
        {
            a[i].first=-a[i].first;
            a[i].second=-a[i].second;
        }
        if(a[i].second<0&&a[i].first<0)
        {
            a[i].second=-a[i].second;
            a[i].first=-a[i].first;
        }
        m[a[i]]++;
    }
    ll ans=1;
    // cout<<endl;
    for(auto it:m)
    {
        // cout<<it.first.first<<" "<<it.first.second<<endl;
        if(it.first.first<0)
        {
            if(m.find({it.first.second,-it.first.first})==m.end())
            ans=(ans*(it.second+1))%mod;
            // cout<<ans<<endl;
            continue;
        }
        ll p=it.second;
        ll q=0;
        if(m.find({-it.first.second,it.first.first})!=m.end());
        {
            q=m[{-it.first.second,it.first.first}];
        }

        ll res=(powe[p]-1+powe[q]-1)%mod;
        ans=(ans*(res+1))%mod;
        // cout<<ans<<endl;
    }
    cout<<ans-1<<endl;

}


#include <bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < (n); i++)
using namespace std;
using ll = long long;
using P = pair<int, int>;

const inf INF = 1001001001;
vector<int> to[100005]

int main() {
    int n, m;
    cin >> n >> m;
    rep(i, m){
        int a, b;
        cin >> a >> b;
        --a; --b;
        to[a].push_back(b);
        to[b].push_back(a);
    }

    queue<int> q;
    vector<int> dist(n, INF);
    vector<int> pre(n, -1);
    dist[0] = 0;
    q.push(0);
    while(!q.empty()){
        int v = q.front(); q.pop();
        for (int u: to[v]){
            if(dist[u] != INF) continue;
            dist[u] = dist[v] + 1;
            pre[u] = v;
            q.push(u);
        }
    }

    cout << "Yes" << endl;
    rep(i, n){
        if(i == 0) continue;
        int ans = pre[i];
        ++ans;
        cout << ans << endl;
    }

    return 0;
}


#include <stdio.h>

int main(void){

    int N = 0;
    scanf("%d", &N);
    N %= 10;

    if (N == 3){
        puts("bon");
    } else if (N == 0 || N == 1 || N == 6 || N == 8){
        puts("pon");
    } else {
        puts("hon");
    }

    return 0;
}


#include <stdio.h>
int main()
{
	int n;
	scanf("%d",&n);
	n=n%10;
	if(n==2||n==4||n==5||n==7||n==9) printf("hon");
	else if(n==3) printf("bon");
	else printf("pon");
	return 0;
}


#include<stdio.h>

int main(void){
    int n;
    scanf("%d",&n);
    int s = n % 10;
    if(s == 2 || s == 4 || s == 5 || s == 7 || s == 9)puts("hon");
    else if(s == 3)puts("bon");
    else puts("pon");
}


#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
//    int a[5]={2,4,5,7,9};
//    int b[4]={0,1,6,8};
//    int c[1]={3};
    cin>>n;
    //cout<<n;
    vector<int>m;
    while(n>0){
        int k=n%10;
        m.push_back(k);
        n/=10;
        //cout<<n<<endl;
    }
    //cout<<n<<endl;
    //m.push_back(n);
    for(int i=0;i<m.size();i++){
        //cout<<m[i]<<" ";
        if(m[i]==3){
            cout<<"bon"<<endl;
            break;
        }
        else if(m[i]==0||m[i]==1||m[i]==6||m[i]==8){
            cout<<"pon"<<endl;
            break;
        } else {
            cout<<"hon"<<endl;
            break;
        }
    }
}


#include <stdio.h>

int a,num,c;

int main(){
	scanf("%d",&a);
    num = a/100;
    switch (num) {
            case 2:
            case 4:
            case 5:
            case 7:
            case 9:
                printf("hon");
                break;
            case 0:
            case 1:
            case 6:
            case 8:
                printf("pon");
                break;
            case 3:
                printf("bon");
                break;
            default:
                printf("Out of range");
                break;
        }
	return 0;
}


#include<iostream>
using namespace std;
int main()
{
  int N;
  cin>>N;
  int ans=N%10;
  if(ans=2||4||5||7||9)
  {
    cout<<"hon"<<endl;
  }
  else if(ans=0||1||6||8)
  {
    cout<<"pon"<<endl;
  }
  else (ans==3)
  {
  cout<<"bon"<<endl;
}
  return 0;
}


const main = (input) => {
  const n = Number(input)
  const nOne = n % 10
  if (nOne === 2 || nOne === 4 || nOne === 5 || nOne === 7 || nOne === 9) {
    console.log('hon')
  } else if (nOne === 0 || nOne === 1 || nOne === 6 || nOne === 8) {
    console.log('pon')
  } else {
    console.log('bon')
  }
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'))


function Main(input) {
    input = input.split("\n");
    tmp = input[0].split(" ");
    var a = parseInt(input[0].slice(-1), 10)

    if ([2,4,5,7,9].indexOf(a)>=0) {
    	console.log("hon")
    }else if([0,1,6,8].indexOf(a)>=0) {
    	console.log("pon")
    }else{
    	console.log("bon")
    }
}

Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function Main(input) {
  input = input.trim();
  var N = input;

  var Ns = N.split("");

  var saigo = Ns[Ns.length - 1];
  if (saigo == "3") {
    console.log("bon");
    return;
  } else if (saigo == "0" || saigo == "1" || saigo == "6" || saigo == "8") {
    console.log("pon");
    return;
  } else {
    console.log("hon");
    return;
  }
}

Main(require("fs").readFileSync("/dev/stdin", "utf8"));


"use strict";

const main = (input) => {
    const spi = input.split('\n');
    const n = parseInt(spi[0]);
    n = (n % 100) % 10;

    if (n === 3) console.log("bon");
    else if (n === 0 || n === 1 || n === 6 || n === 8) console.log("pon");
    else console.log("hon");
};

main(require("fs").readFileSync("/dev/stdin", "utf8"));


// AUTHOR:: MOHAMAMD FAISAL

"use strict";

const main = (input) =>{

  //const arr = input.trim().split("");
//  const firstplace = arr[arr.length -1];
  const firstplace = input%10;

  if(firstplace ==3)
    console.log("bon");
  else if(firstplace==0 || firstplace==1 || firstplace==6 || firstplace==8)
    console.log("pon");
  else
    console.log("hon");
};

main(require("fs").readFileSync("dev/stdin","utf-8"));


// AUTHOR:: MOHAMAMD FAISAL

"use strict";

const main = (input) =>{

  const arr = input.trim().split("");
  const firstplace = arr[arr.length -1];

  if(firstplace ==3)
    console.log("bon");
  else if(firstplace==0 || firstplace==1 || firstplace==6 || firstplace==8)
    console.log("pon");
  else
    console.log("hon");
};

main(require("fs").readFileSync("dev/stdin","utf-8"));


package main

import "fmt"

func main() {
	var n int
	fmt.Scan(&n)
	firstPlaceNum := n % 10
	switch firstPlaceNum {
	case 2,4,5,7,9:
		fmt.Println("hon")
	case 0,1,6,8:
		fmt.Println("pon")
	case 3:
		fmt.Println("bon")
	}
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// go run ./ABC168/A\ -\ ∴\ \(Therefore\)/main.go < in

func main() {
	sc := bufio.NewScanner(os.Stdin)
	var inputLastStr string
	for i := 0; i <= 0; i++ {
		sc.Scan()
		inputs := strings.Split(sc.Text(), "")
		inputLastStr = inputs[len(inputs)-1]
	}
	input, _ := strconv.Atoi(inputLastStr)

	judge(input)
}

func judge(callTarget int) {
	if callTarget == 2 || callTarget == 4 || callTarget == 5 || callTarget == 7 || callTarget == 9 {
		fmt.Println("hon")
	} else if callTarget == 0 || callTarget == 1 || callTarget == 6 || callTarget == 8 {
		fmt.Println("pon")
	} else if callTarget == 3 {
		fmt.Println("bon")
	}
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

var (
	input  = bufio.NewScanner(os.Stdin)
	tokens []string
)

// genTokens generates tokens from the input, and puts it into the tokens array.
func genTokens() {
	if !input.Scan() {
		panic("No more input")
	}

	nextFields := strings.Fields(input.Text())
	tokens = append(tokens, nextFields...)
}

// nextInt returns next int in its input, or panics if no input.
func nextInt() int {
	if len(tokens) == 0 {
		genTokens()
	}
	if len(tokens) == 0 {
		panic("No more input")
	}

	next := tokens[0]
	tokens = tokens[1:]

	ret, err := strconv.Atoi(next)
	if err != nil {
		panic(err)
	}
	return ret
}

// nextInt64 returns next int in its input, or panics if no input.
func nextInt64() int64 {
	if len(tokens) == 0 {
		genTokens()
	}
	if len(tokens) == 0 {
		panic("No more input")
	}

	next := tokens[0]
	tokens = tokens[1:]

	ret, err := strconv.ParseInt(next, 10, 64)
	if err != nil {
		panic(err)
	}
	return ret
}

// next returns the next string separated by spaces, or panics if no input.
func next() string {
	if len(tokens) == 0 {
		genTokens()
	}
	if len(tokens) == 0 {
		panic("No more input")
	}

	next := tokens[0]
	tokens = tokens[1:]

	return next
}

func main() {
	n := nextInt()
	switch n % 10 {
	case 2:
		fallthrough
	case 4:
		fallthrough
	case 5:
		fallthrough
	case 7:
		fallthrough
	case 9:
		fmt.Println("hon")
	case 0:
		fallthrough
	case 1:
		fallthrough
	case 6:
		fallthrough
	case 8:
		fmt.Println("pon")
	case 3:
		fmt.Println("bon")
	}
}


package main

import (
	"fmt"
)

func main() {
	a := 0
	fmt.Scanf("%d", a)
	a %= 10
	switch a {
	case 2, 4, 5, 7, 9:
		fmt.Println("hon")
	case 0, 1, 6, 8:
		fmt.Println("pon")
	default:
		fmt.Println("bon")
	}
}


package main

import "fmt"

func main() {
	var n int

	fmt.Scanf("%d", &n)

	hon_list := []int{2,4,5,7,9}

	pon_list := []int{0,1,6,8}

	if contains(hon_list, n)  {
		fmt.Printf("hon")
	} else if contains(pon_list, n) {
		fmt.Printf("pon")
	} else {
		fmt.Printf("bon")
	}
}

func contains(arr []int, i int) bool {
	for _, a := range arr {
		if a == i {
			return true
		}
	}
	return false
}


package main

import "fmt"

func main() {
	var n int
  	fmt.Scanf("%d", &n)

  	sup := n%10

  if sup == 3 {
    fmt.Println("bon")
  }else if (sup ==2 || sup == 4 || sup == 5 || sup == 7 || sup == 8 || sup == 9 ) {
    fmt.Println("hon")
  }else {
    fmt.Println("pon")
  }
}


n = gets.chomp.to_i

amari = n % 10

if amari == 2  || amari == 4 || amari == 5 || amari == 7 ||  amari == 9
  print "hon\n"
elsif amari == 0 || amari == 1 || amari == 6 || amari == 8
  print "pon\n"
else
  print "bon\n"
end


N = gets.chomp[-1].to_i
case N
when 2,4,5,7,9
  puts 'hon'
when 0,1,6,8
  puts 'pon'
when 3
  puts 'bon'
end


case gets.chomp.split('').last.to_i
when 2, 4, 5, 7, 9
  puts 'hon'
when 0, 1, 6, 8
  puts 'pon'
when 3
  puts 'bon'
end


n = gets.chomp.to_i

if [2, 4, 5, 7, 9].include? n[-1]
  puts 'hon'
elsif [0, 1, 6, 8].include? n[-1]
  puts 'pon'
else
  puts 'bon'
end


n = gets.split('').map(&:to_i)
bon = [3]
pon = [0, 1, 6, 8]

if bon.include?(n[-1])
  puts 'bon'
elsif pon.include?(n[-1])
  puts 'pon'
else puts 'hon'
end


s=gets.chomp
if [2,4,5,7,9].include? s[-1]
  puts 'hon'
elsif [0,1,6,8].include? s[-1]
  puts 'pon'
else
  puts 'bon'
end


use proconio::input;

fn main() {
  input! {
    n: i32
  }

  println!("{}", match n % 10 {
    2 | 4 | 5 | 7 | 9 => "hon",
    0 | 1 | 6 | 8 => "pon",
    3 => "bon",
    _ => "_"
  });
}


use proconio::{fastout, input};

#[fastout]
fn main() {
    input! {
        n: u64,
    }
    let ans = match n % 10 {
        2 | 4 | 5 | 7 | 9 => "hon",
        0 | 1 | 6 | 8 => "pon",
        3 => "bon",
        _ => unreachable!(),
    };
    println!("{}", ans);
}


#![allow(unused_imports)]
use std::cmp::*;
use std::collections::*;
use itertools::Itertools;
use proconio::{input, marker::*, fastout};
use superslice::*;

#[fastout()]
fn main() {
    input! {
        n: usize
    }
    match n % 10 {
        2|4|5|7|9 => println!("hon"),
        0|1|6|8 => println!("pon"),
        _ => println!("bon"),
    }
}


use proconio::input;

fn main() {

  let mut _n : usize ;
  let mut _d : String ;

    input! {

      mut n : usize ,
      mut d : String ,
    }

     let  length = d.len();

      if length > n{
        let s = &d[0..n];
      println!("{}...",s);

     }else   {

      println!("{}",d);

     }

}


use proconio::input;

fn main() {

  let mut _n : usize ;
  let mut _d : String ;

    input! {

      mut n : usize ,
      mut d : String ,
    }

     let  length = d.len();
     let s = &d[0..n];

      if length > n{

      println!("{}... ",s);

     }else {

      println!(".. ");

     }
}


use proconio::input;

fn main() {
    input! {
        n: i32
    }

    solve(n);
}

fn solve(n: i32) {
    match n % 10 {
        2 => println!("hon"),
        4 => println!("hon"),
        5 => println!("hon"),
        7 => println!("hon"),
        9 => println!("pon"),
        0 => println!("pon"),
        1 => println!("pon"),
        6 => println!("pon"),
        8 => println!("pon"),
        _ => println!("bon"),
    }
}


let c = Int(readLine()!)!

switch c%10 {
case 2,4,5,7,9:
    print("hon")
 break
case 0,1,6,8:
    print("pon")
    break
case 3:
    print("bon")
    break
default:
    break
}


let N = Int(readLine()!)!
let digit = N % 10
if digit == 2 || digit == 4 || digit == 5 || digit == 7 ||
  digit == 9 {
  print("hon")
} else if digit == 0 || digit == 1 || digit == 6 || digit == 8 {
  print("pon")
} else {
  print("bon")
}


let value = Int(readLine()!)!
let pon = "pon"
let hon = "hon"
let bon = "bon"
let table = [pon, pon, hon, bon, hon, hon, pon, hon, pon, hon]

print(table[value % 10])


import UIKit

var b = (Float(readLine()!)!).remainder(dividingBy: 10.0);

if(b == 2 || b == 4 || b == 5 || b == 7 || b == 9)
{
    print("hon")
}
else if(b == 0 || b == 1 || b == 6 || b == 8)
{
    print("pon")
}
else
{
    print("bon")
}


import UIKit

var b = (Int(readLine()!)! % 10);


import UIKit

var a = readLine()!;
var b = (Int(a)! % 10);

if(b == 2 || b == 4 || b == 5 || b == 7 || b == 9)
{
    print("hon")
}
else if(b == 0 || b == 1 || b == 6 || b == 8)
{
    print("pon")
}
else
{
    print("bon")
}


/**
 * https://atcoder.jp/contests/abc168/tasks/abc168_a
 *
 * いろはちゃんは、人気の日本製ゲーム「ÅtCoder」で遊びたい猫のすぬけ君のために日本語を教えることにしました。
 * 日本語で鉛筆を数えるときには、助数詞として数の後ろに「本」がつきます。
 * この助数詞はどんな数につくかで異なる読み方をします。
 * 具体的には、999 以下の正の整数 N について、「N 本」と言うときの「本」の読みは
 * N の 1 の位が 2,4,5,7,9 のとき hon
 *・N の 1 の位が 0,1,6,8 のとき pon
 *・N の 1 の位が 3 のとき bonです。
 *・N が与えられるので、「N 本」と言うときの「本」の読みを出力してください。
 *
 * 制約
 * N は 999 以下の正の整数
 */
export function Main(input: string) {
  // 問題文解体エリア
  const num = Number(input).valueOf();

  // console.log(nums);
  // 問題解決エリア
  const answer = fuck(num);

  //出力エリア
  console.log(answer.toString());
}

//*この行以降は編集しないでください（標準入出力から一度に読み込み、Mainを呼び出します）
// 提出する時にコメントアウト解除せよ
Main(require("fs").readFileSync("/dev/stdin", "utf8"));

export function fuck(num:number): string {
  const hons = ["2", "4", "5", "7", "9"];
  const pons = ["0", "1", "6", "8"];
  const bons = ["3"];

  const numStr = num.toString();
  const numOn1 = numStr.substr(numStr.length - 1);
  if (hons.indexOf(numOn1) >= 0) {
    return "hon";
  } else if (pons.indexOf(numOn1) >= 0) {
    return "pon";
  } else if (bons.indexOf(numOn1) >= 0) {
    return "bon";
  }
  return "fuck";
}


import * as fs from 'fs';

const readString = (() => {
  const input = fs.readFileSync(0).toString();
  const words = input.split(/[ \n]/);
  let i = 0;
  return () => words[i++] || '';
})();
const readInt = () => parseInt(readString(), 10);

(function main() {
  const N = readInt();
  let o;
  switch (N % 10) {
    case 2:
    case 4:
    case 5:
    case 7:
    case 9:
      o = 'hon';
      break;
    case 0:
    case 1:
    case 6:
    case 8:
      o = 'pon'
      break;
    case 3:
      o = 'bon';
      break;
  }
  console.log(o);
})();


import * as fs from 'fs'
import {debug} from '../../../util'

const input = fs.readFileSync('/dev/stdin', 'utf8').trim()

const output = (x: string | number | boolean) => console.log(x)
const splitLine = (string: string): string[] => string.split('\n')
const splitBlank = (string: string): string[] => string.split(' ')
const toNumbers = (array: string[]): number[] => array.map(v => Number(v))
const createSerialNumber = (n: number): number[] => [...Array(n).keys()]

// debug(input)

/* ここから */
const m = input.slice(-1)
if (m == '2' || m == '4' || m == '5' || m == '7' || m  == '9') {
    output('hon')
} else if (m == '3') {
    output('bon')
} else {
    output('pon')
}


import * as fs from 'fs';

const input = fs.readFileSync("/dev/stdin", "utf8").toString();

const fp = input[input.length - 1];

if(new Set(['2', '4', '5', '7', '9']).has(fp)) {
  console.log('hon');
}else if(new Set(['0', '1', '6', '8']).has(fp)) {
  console.log('pon');
} else {
  console.log('bon');
}


import * as fs from 'fs';

const input = String(fs.readFileSync("/dev/stdin", "utf8"));

const fp = input.slice(-1);

if(new Set(['2', '4', '5', '7', '9']).has(fp)) {
  console.log('hon');
}else if(new Set(['0', '1', '6', '8']).has(fp)) {
  console.log('pon');
} else {
  console.log('bon');
}


import * as fs from 'fs';

const input = String(fs.readFileSync("/dev/stdin", "utf8"));

const fp = input.slice(-1);

if(['2','4','5','7','9'].includes(fp)) {
  console.log('hon');
}else if(['0','6','1','8'].includes(fp)) {
  console.log('pon');
} else {
  console.log('bon');
}


N = int(input())
X = list(map(int, input().split()))

def variance(x):
    avg = sum(X) // len(X)
    return (avg - x) ** 2

def main(X):
    tot = 0
    tot2 = 0
    for x in X:
        tot += variance(x)
        tot2 += variance(x - 1)
    return min(tot, tot2)

ans = main(X)
print(ans)


n=int(input())
x=list(map(int,input().split()))
sum=0
for i in x:
  sum+=i
t=round(sum/n)
sum=0
for i in x:
  sum+=(t-i)**2
print(sum)


N = int(input())
X_list = list(map(int, input().split()))

P = round(sum(X_list) / N)
ans = 0
for i in range(N):
    ans += (X_list[i] - P) ** 2
print(ans)


import sys
def LI(): return list(map(int, sys.stdin.buffer.readline().split()))
def I(): return int(sys.stdin.buffer.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 10 ** 9 + 7
import math
import statistics
n = I()
xl = LI()

# n人が消費する体力の総和の最小値
# 数直線上にn人が住んでいる
# i番目がXi
# n人全員が参加する集会
# 任意の整数値の座標で集会を開く。座標pで集会を開くときはi番目の人は(Xi-p))**2の体力を消費する。

xl_mean = math.ceil(statistics.mean(xl))

sigma_pow = sum([(x-xl_mean)**2 for x in xl])

print(sigma_pow)


N=int(input())
X=list(map(int,input().split()))
X.sort()

ans=10**1000
for p in range(X[0],X[-1]):
    tmp=0
    for x in X:
        tmp+=(x-p)**2
    ans=min(ans,tmp)
print(ans)


N=int(input())
X=list(map(int,input().split()))
X.sort()

ans=10**10
for p in range(X[0],X[-1]):
    tmp=0
    for x in X:
        tmp+=(x-p)**2
    ans=min(ans,tmp)
print(ans)


import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import java.util.Map.Entry;
// import static java.util.Arrays.compare;
import static java.util.Arrays.fill;
import static java.util.Arrays.sort;
import static java.util.Collections.sort;
import static java.util.Comparator.reverseOrder;
// import static java.util.List.of;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.Objects.hash;

import java.io.*;

import java.math.BigInteger;
import static java.math.BigInteger.ZERO;
import static java.math.BigInteger.ONE;
// import static java.math.BigInteger.TWO;
import static java.math.BigInteger.TEN;

import static java.lang.Math.PI;
import static java.lang.Math.E;
import static java.lang.Math.min;
import static java.lang.Math.max;
import static java.lang.Math.abs;
import static java.lang.Math.sin;
import static java.lang.Math.cos;
import static java.lang.Math.tan;
import static java.lang.Math.asin;
import static java.lang.Math.acos;
import static java.lang.Math.atan;
import static java.lang.Math.atan2;
import static java.lang.Math.hypot;
import static java.lang.Math.sqrt;
import static java.lang.Math.log;
import static java.lang.Math.exp;
import static java.lang.String.format;
import static java.lang.System.exit;
import static java.lang.System.currentTimeMillis;
public class Main{
   public static void main(String[] args) {
      FastScanner fsc = new FastScanner();
      int n = fsc.nextInt();
      int sqs = 0, s = 0;
      for (int i = 0; i < n; i++) {
         int x = fsc.nextInt();
         s += x;
         sqs += x * x;
      }
      System.out.println(Math.min(d(s / n, n, s, sqs), d(s / n + 1, n, s, sqs)));
   }

   public static int d(int i, int n, int s, int sqs) {
      return n * i * i - 2 * s * i + sqs;
   }
}

class ArrayUtil{
    public static int[] map(IntUnaryOperator op, int[] a){
        int[] b=new int[a.length];
        for(int i=0;i<a.length;i++) b[i] = op.applyAsInt(a[i]);
        return b;
    }
    /**
     * s[i] is the sum of the range [0, i) in a.
     * @param a
     * @return cumulative sum array of a.
     */
    public static int[] cumsum(int[] a){
        int n=a.length;
        int[] s=new int[n+1];
        for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i-1];
        return s;
    }
    public static int[][] cumsum(int[][] a){
        int n=a.length;
        int m=a[0].length;
        int[][] s=new int[n+1][m+1];
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i-1][j-1];
        return s;
    }
    public static void reverse(int[] a, int begin, int end){
        for(int i=begin;i<begin+(end-begin)/2;i++) swap(a, i, begin+end-i-1);
    }
    public static void reverse(int[] a){
        reverse(a, 0, a.length);
    }
    public static void revSort(int[] a){
        Arrays.sort(a);
        reverse(a);
    }
    public static int[] nextPermutation(int[] a){
        int[] ret=a.clone();
        int n=ret.length;
        for(int i=n-1;i>=1;i--){
            if(ret[i]>ret[i-1]){
                int fail=n, pass=i;
                while(fail-pass>1){
                    int mid=pass+(fail-pass)/2;
                    if(ret[mid]>ret[i-1]) pass=mid;
                    else fail=mid;
                }
                swap(ret, pass, i-1);
                reverse(ret, i, n);
                return ret;
            }
        }
        return null;
    }
    public static int[] predPermutation(int[] a){
        int[] ret=a.clone();
        int n=ret.length;
        for(int i=n-1;i>=1;i--){
            if(ret[i]<ret[i-1]){
                int fail=n, pass=i;
                while(fail-pass>1){
                    int mid=pass+(fail-pass)/2;
                    if(ret[mid]<ret[i-1]) pass=mid;
                    else fail=mid;
                }
                swap(ret, pass, i-1);
                reverse(ret, i, n);
                return ret;
            }
        }
        return null;
    }
    public static void swap(int[] a, int u, int v){
        int tmp=a[u];
        a[u]=a[v];
        a[v]=tmp;
    }
    public static int compare(int[] a, int[] b){
        for(int i=0;i<a.length;i++){
            if(i>=b.length){
                return -1;
            } else if(a[i]>b[i]){
                return 1;
            } else if(a[i]<b[i]){
                return -1;
            }
        }
        if(a.length<b.length){
            return 1;
        } else{
            return 0;
        }
    }
    public static boolean equals(int[] a, int[] b){
        return compare(a, b)==0;
    }

    /*      IntArray
     * _________________________
     *      LongArray
     */
    public static long[] map(LongUnaryOperator op, long[] a){
        long[] b=new long[a.length];
        for(int i=0;i<a.length;i++) b[i]=op.applyAsLong(a[i]);
        return b;
    }
    /**
     * s[i] is the sum of the range [0, i) in a.
     * @param a
     * @return cumulative sum array of a.
     */
    public static long[] cumsum(long[] a){
        int n=a.length;
        long[] s=new long[n+1];
        for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i-1];
        return s;
    }
    public static long[][] cumsum(long[][] a){
        int n=a.length;
        int m=a[0].length;
        long[][] s=new long[n+1][m+1];
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i-1][j-1];
        return s;
    }
    public static void reverse(long[] a, int begin, int end){
        for(int i=begin;i<begin+(end-begin)/2;i++) swap(a, i, begin+end-i-1);
    }
    public static void reverse(long[] a){
        reverse(a, 0, a.length);
    }
    public static void revSort(long[] a){
        Arrays.sort(a);
        reverse(a);
    }
    public static void compress(long[] a){
        int n=a.length;
        long[] sorted = a.clone();
        Arrays.sort(sorted);
        for(int i=0;i<n;i++){
            int l=0, r=n;
            while(r-l>1){
                int m=l+(r-l)/2;
                if(sorted[m]<=a[i]) l=m;
                else r=m;
            }
            a[i]=l;
        }
    }
    public static void swap(long[] a, int u, int v){
        long tmp=a[u];
        a[u]=a[v];
        a[v]=tmp;
    }
    public static int compare(long[] a, long[] b){
        for(int i=0;i<a.length;i++){
            if(i>=b.length){
                return -1;
            } else if(a[i]>b[i]){
                return 1;
            } else if(a[i]<b[i]){
                return -1;
            }
        }
        if(a.length<b.length){
            return 1;
        } else{
            return 0;
        }
    }
    public static boolean equals(long[] a, long[] b){
        return compare(a, b)==0;
    }
}

class BellmanFord{
    public long[] bellmanFord(Node[] nodes, int s){
        int n = nodes.length;
        boolean negativeLoop[] = new boolean[n];
        long[] d = new long[n];
        fill(d, Const.LINF);
        d[s] = 0;
        for(int i = 0; i < n; i++){
            for(int from = 0; from < n; from++){
                for(Edge edge: nodes[from].edges){
                    int to = edge.to;
                    long c = edge.cost;
                    if(d[to] > d[from] + c){
                        d[to] = d[from] + c;
                    }
                }
            }
        }
        for(int i = 0; i < n; i++){
            for(int from = 0; from < n; from++){
                for(Edge edge: nodes[from].edges){
                    int to = edge.to;
                    long c = edge.cost;
                    if(d[to] > d[from] + c){
                        negativeLoop[to] = true;
                        d[to] = -Const.LINF;
                    }
                    if(negativeLoop[from]){
                        negativeLoop[to] = true;
                        d[to] = -Const.LINF;
                    }
                }
            }
        }
        return d;
    }
}

/**
 * BinaryIndexedTree(n=10): [ 8 ] [ 4 ] [ 2 ] [ 6 ] [ 10 ] [1] [3] [5] [7] [9]
 *
 * original array: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
 *
 * if you want to get the sum of range (l, r], caluculate S(r)-S(l). (S(n) means
 * \sum_{i=1}^n array[i].)
 *
 * then, you need to be able to calculate S(n) quickly. actually, you can.
 *
 * 1. binarize n. Ex: n=5(10)=101(2). 2. decompose
 * n=2**p_1+2**p_2+...+2**p_m.(p_1<...<p_m) Ex: n=1+100. 3. acutually,
 * S(n)=\sum_{i=1}^m{tree[\sum_{j=i}^m 2**p_j]} Ex: S(n)=tree[101]+tree[100].
 *
 * computational complexity of sum-query is O(log n).
 */

class BinaryIndexedTree{
    private int[] tree;
    private int[] originalArray;
    private int n;
    /**
     * @param array 0-indexed array.
     */
    public BinaryIndexedTree(int[] array){
        this.originalArray = array.clone();
        this.n = array.length;
        this.tree = new int[n+1];
        init();
    }
    public BinaryIndexedTree(int initial, int n){
        this.originalArray = new int[n];
        this.n = n;
        this.tree = new int[n+1];
        for(int i = 0; i < n; i++) originalArray[i] = initial;
        init();
    }
    public BinaryIndexedTree(int n){
        this(0, n);
    }
    private void init(){
        for(int i = 1; i <= n; i++){
            tree[i] += originalArray[i-1];
            int parent = i + (-i & i);
            if(parent <= n) tree[parent] += tree[i];
        }
    }

    /**
     * Calculate the sum of range (l, r] in array (1-indexed).
     * @param l left border (open)
     * @param r right border (closed)
     * @return sum of range (l, r] in array (1-indexed).
     */
    public int sum(int l, int r){
        return sum(r) - sum(l);
    }
    public int sum(int r){
        int ret = 0;
        for(; r > 0; r -= -r & r) ret += tree[r];
        return ret;
    }
    public int sum(){
        return sum(n);
    }

    /**
     * add v to array[i] and update BIT.
     * @param i index of array (1-indexed)
     * @param v adding value
     */
    public void add(int i, int v){
        originalArray[i-1] += v;
        for(; i <= n; i += -i & i) tree[i] += v;
    }

    /**
     * update the value of array[i] to v and update BIT.
     * @param i index of array (1-indexed)
     * @param v adding value
     */
    public void update(int i, int v){
        add(i, v - originalArray[i-1]);
        originalArray[i] = v;
    }

    @Override
    public String toString(){
        int msb=0;
        for(int m=n;m>>1!=0;m>>=1, msb++);
        char[][] c=new char[msb+1][1<<(2*msb+1)];
        int[] indx=new int[msb+1];
        for(int i=1;i<=n;i++){
            int j=0;
            for(int l=-i&i;l>>1!=0;l>>=1, j++);
            char[] intc=Integer.toString(tree[i]).toCharArray();
            int intl=intc.length;
            c[j][indx[j]]='[';
            c[j][indx[j]+(1<<(j+2))-1]=']';
            int st=indx[j]+(1<<(j+1))-intl/2-1;
            for(int l=0;l<intl;l++){
                c[j][st+l]=intc[l];
            }
            indx[j]+=1<<(j+3);
        }
        StringBuilder sb=new StringBuilder();
        for(int i=msb;i>=0;sb.append(String.valueOf(c[i--])).append("\n"));
        return sb.toString();
    }
}

class Const{
    public static final long MOD7 = 1_000_000_007;
    public static final long MOD9 = 1_000_000_009;
    public static long MOD = MOD7;
    public static final long LINF = 1_000_000_000_000_000_000l;
    public static final int IINF = 1_000_000_000;
    public static void setMod(long mod){
        MOD = mod;
    }
}

class Dijkstra{
    public static PrevAndDist dijkstra(Node[] nodes, int s){
        int n = nodes.length;
        int[] prev = new int[n];
        long[] d = new long[n];
        Queue<Integer> pq = new PriorityQueue<>((u, v) -> Long.compare(d[u], d[v]));
        fill(d, Const.LINF);
        d[s] = 0;
        pq.add(s);
        while(pq.size() > 0){
            int now = pq.poll();
            for(Edge e: nodes[now].edges){
                int next = e.to;
                long c = e.cost;
                if(d[now] + c < d[next]){
                    d[next] = d[now] + c;
                    prev[next] = now;
                    pq.add(next);
                }
            }
        }
        return new PrevAndDist(prev, d);
    }

    public static int[] path(PrevAndDist pd, int from, int to){
        ArrayList<Integer> rev=new ArrayList<>();
        for(int now = to; now != from; now = pd.prev[now]) rev.add(now);
        rev.add(from);
        int[] path = new int[rev.size()];
        for(int i = 0; i < path.length; i++) path[i] = rev.get(path.length - i - 1);
        return path;
    }

    public static class PrevAndDist{
        public int[] prev;
        public long[] d;
        public PrevAndDist(int[] prev, long[] d){
            this.prev=prev;
            this.d=d;
        }
    }
}

//caluculate maximum-flow in O(|E|*|V|^2), but often fast.
class Dinic{
    public static long dinic(int s, int t, Node[] nodes) {
        long flow = 0;
        while(true){
            int[] level = bfs(s, t, nodes);
            if(level[t] < 0) break;
            int[] iter = new int[nodes.length];
            long f = dfs(s, t, nodes, Const.LINF, level, iter);
            while (f > 0) {
                flow += f;
                f = dfs(s, t, nodes, Const.LINF, level, iter);
            }
        }
        return flow;
    }

    private static int[] bfs(int s, int t, Node[] nodes) {
        IntQueue iq = new IntQueue(nodes.length);
        iq.addLast(s);
        int[] level = new int[nodes.length];
        fill(level, -1);
        level[s] = 0;
        while (iq.size() > 0) {
            int now = iq.pollFirst();
            for (Edge e : nodes[now].edges) {
                if (level[e.to] < 0 && e.cap > 0) {
                    iq.addLast(e.to);
                    level[e.to] = level[now] + 1;
                }
            }
        }
        return level;
    }

    private static long dfs(int now, int t, Node[] nodes, long f, int[] level, int[] iter) {
        if (now == t) return f;
        for (int i = iter[now]++; i < nodes[now].edges.size(); i++) {
            Edge e = nodes[now].edges.get(i);
            if (level[now] < level[e.to] && e.cap > 0) {
                long d = dfs(e.to, t, nodes, Math.min(f, e.cap), level, iter);
                if (d > 0) {
                    e.cap -= d;
                    nodes[e.to].edges.get(e.rev).cap += d;
                    return d;
                }
            }
        }
        return 0;
    }
}

class Edge{
    public int from, to;
    public long cost;
    public long cap;
    public int rev;
    public Edge(int to, long cap, int rev) {
        this.to = to;
        this.cap = cap;
        this.rev = rev;
    }
    public Edge(int from, int to, long cost){
        this.from = from;
        this.to = to;
        this.cost=cost;
    }
    public Edge(int from, int to){
        this.from = from;
        this.to = to;
    }
    public Edge(int to, long cost){
        this.to = to;
        this.cost = cost;
    }
}

class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
        return (int) nl;
    }
    public double nextDouble() { return Double.parseDouble(next());}
}

// caluculate maximum-flow in O(|E|*F). F is the maximum-flow.
class FordFulkerson{
    static long fordFulkerson(int s, int t, Node[] nodes) {
        long flow = 0;
        while (true) {
            boolean[] used = new boolean[nodes.length];
            long f = dfs(s, t, nodes, Const.LINF, used);
            flow += f;
            if(f <= 0) break;
        }
        return flow;
    }

    private static long dfs(int now, int t, Node[] nodes, long f, boolean[] used) {
        if(now == t) return f;
        used[now] = true;
        for (int i = 0; i < nodes[now].edges.size(); i++) {
            Edge e = nodes[now].edges.get(i);
            if (!used[e.to] && e.cap > 0) {
                long d = dfs(e.to, t, nodes, Math.min(f, e.cap), used);
                if (d > 0) {
                    e.cap -= d;
                    nodes[e.to].edges.get(e.rev).cap += d;
                    return d;
                }
            }
        }
        return 0;
    }
}

class Graph{
    public Node[] nodes;
    public Edge[] edges;
    public int n;
    public int m;

    private int mIndx = 0;

    public Graph(int n, int m){
        this.nodes = new Node[n];
        for(int i = 0; i < n; i++) nodes[i] = new Node(i);
        this.edges = new Edge[m];
        this.n = n;
        this.m = m;
    }

    public void addDirectedEdge(int from, int to, long cost){
        Edge e = new Edge(from, to, cost);
        nodes[from].edges.add(e);
        nodes[to].in++;
        edges[mIndx++] = e;
    }
    public void addNonDirectedEdge(int from, int to, long cost){
        Edge e = new Edge(from, to, cost);
        Edge er = new Edge(to, from, cost);
        nodes[from].edges.add(e);
        nodes[to].edges.add(er);
        nodes[from].in++;
        nodes[to].in++;
        edges[mIndx++] = e;
    }
    public void addDirectedEdge(int from, int to){
        addDirectedEdge(from, to, 1l);
    }
    public void addNonDirectedEdge(int from, int to){
        addNonDirectedEdge(from, to, 1l);
    }
    public void addCapEdge(int from, int to, long cap) {
        nodes[from].edges.add(new Edge(to, cap, nodes[to].edges.size()));
        nodes[to].edges.add(new Edge(from, 0l, nodes[from].edges.size() - 1));
    }
    public void setNodeWeight(long[] w){
        for(int i = 0; i < n; i++) nodes[i].w = w[i];
    }
}

class IntQueue {
    private int[] a;
    private int head = 0, tail = 0;

    public IntQueue(int max) {
        a = new int[max+2];
    }
    public void addLast(int x) {
        a[tail++] = x;
    }
    public int pollFirst() {
        if(tail == head) {
            try { throw new Exception("no elements."); }
            catch (Exception e) { e.printStackTrace(); }
        }
        return a[head++];
    }
    public int pollLast() {
        if(tail == head) {
            try { throw new Exception("no elements."); }
            catch (Exception e) { e.printStackTrace(); }
        }
        return a[--tail];
    }
    public int getFirst() {
        return a[head];
    }
    public int getLast() {
        return a[tail - 1];
    }
    public int size() {
        return tail - head;
    }
    public void init() {
        head = tail = 0;
    }
}

class IntUtil {
    public static int min(int... a) {
        int ret = Const.IINF;
        for (int c : a) ret = Math.min(ret, c);
        return ret;
    }

    public static int max(int... a) {
        int ret = -Const.IINF;
        for (int c : a) ret = Math.max(ret, c);
        return ret;
    }

    /**
     * Caluculate the ceil of a/b. Returns the smallest integer greater than or
     * equal to a/b while 'a/b' rounds fractional parts to ZERO.
     *
     * @param a
     * @param b
     * @return the smallest integer greater than or equal to a/b
     */
    public static int cld(int a, int b) {
        if (a > 0 && b > 0) return (a + b - 1) / b;
        else if (a < 0 && b < 0) return (a + b + 1) / b;
        else return a / b;
    }

    /**
     * Caluculate the floor of a/b. Returns the largest integer less than or equal
     * to a/b while 'a/b' rounds fractional parts to ZERO.
     *
     * @param a
     * @param b
     * @return the largest integer less than or equal to a/b
     */
    public static int fld(int a, int b) {
        if (a <= 0 && b > 0) return (a - b + 1) / b;
        else if (a > 0 && b <= 0) return (a - b - 1) / b;
        else return a / b;
    }

    public static int fold(IntBinaryOperator func, int a, int... b) {
        int ret = a;
        for (int c : b) ret = func.applyAsInt(ret, c);
        return ret;
    }
}

class LazySegmentTree{
    private long[] tree;
    private long[] lazy;
    private long idElm;
    private long defaultLazyValue;
    private LongBinaryOperator operator;
    private LongBinaryOperator updateFunction;
    private LongBinaryOperator mergeLazyFunction;
    private BiFunction<Long, Integer, Long> collapseUpdateFunction;
    private int size;
    private int leafs;
    private int height;
    private int baseOfLeaf;

    public LazySegmentTree(long[] t, LongBinaryOperator operator, long idElm, LongBinaryOperator updateFunction, LongBinaryOperator mergeLazyFunction , BiFunction<Long, Integer, Long> collapseUpdateFunction, long defaultLazyValue){
        int n = t.length;
        this.operator = operator;
        this.idElm = idElm;
        this.updateFunction = updateFunction;
        this.mergeLazyFunction = mergeLazyFunction;
        this.collapseUpdateFunction = collapseUpdateFunction;
        this.defaultLazyValue = defaultLazyValue;
        this.height = minimumPowerOfTwo(n);
        this.leafs = 1 << this.height;
        this.baseOfLeaf = this.leafs - 1;
        this.size = 2 * this.leafs - 1;
        this.lazy = new long[this.size];
        this.tree = new long[this.size];
        for(int i = size - 1; i >= 0; i--) {
            if(i >= baseOfLeaf + n) {
                this.tree[i] = this.idElm;
            } else if(isLeaf(i)) {
                this.tree[i] = t[i - baseOfLeaf];
            } else{
                this.tree[i] = operator.applyAsLong(this.tree[left(i)], this.tree[right(i)]);
            }
        }
    }

    public void applyForSegment(int l, int r, long v){
        applyForSegment(new Range(l, r), 0, new Range(0, leafs), v);
    }
    private long applyForSegment(Range queryRange, int k, Range treeRange, long v){
        evaluate(k, treeRange);
        if(queryRange.crosses(treeRange)) {
            if(queryRange.contains(treeRange)) {
                lazy[k] = mergeLazyFunction.applyAsLong(lazy[k], v);
                return updateFunction.applyAsLong(tree[k], collapseUpdateFunction.apply(lazy[k], treeRange.length()));
            } else {
                long left = applyForSegment(queryRange, left(k), treeRange.leftHalf(), v);
                long right = applyForSegment(queryRange, right(k), treeRange.rightHalf(), v);
                return tree[k] = operator.applyAsLong(left, right);
            }
        } else{
            return tree[k];
        }
    }
    public void applyForPoint(int i, long v){
        tree[baseOfLeaf + i] = updateFunction.applyAsLong(tree[baseOfLeaf + i], collapseUpdateFunction.apply(v, 1));
    }

    public long query(int l, int r){
        return query(new Range(l, r), 0, new Range(0, leafs));
    }
    private long query(Range queryRange, int k, Range treeRange){
        evaluate(k, treeRange);
        if(!queryRange.crosses(treeRange)){
            return idElm;
        } else if(queryRange.contains(treeRange)){
            return tree[k];
        } else{
            long left = query(queryRange, left(k), treeRange.leftHalf());
            long right = query(queryRange, right(k), treeRange.rightHalf());
            return operator.applyAsLong(left, right);
        }
    }
    private void evaluate(int k, Range r){
        if(lazy[k] != defaultLazyValue) {
            if(!isLeaf(k)){
                lazy[left(k)] = mergeLazyFunction.applyAsLong(lazy[left(k)], lazy[k]);
                lazy[right(k)] = mergeLazyFunction.applyAsLong(lazy[right(k)], lazy[k]);
            }
            tree[k] = updateFunction.applyAsLong(tree[k], collapseUpdateFunction.apply(lazy[k], r.length()));
            lazy[k] = defaultLazyValue;
        }
    }
    private int minimumPowerOfTwo(int n){
        int i = 0;
        while(1 << ++i < n);
        return i;
    }
    private boolean isLeaf(int i){
        return i >= baseOfLeaf;
    }
    private int left(int k){
        return 2 * k + 1;
    }
    private int right(int k){
        return 2 * k + 2;
    }

    public String toString(){
        StringBuilder sb = new StringBuilder();
        for(int h = 0; h <= height; h++) {
            for(int i = (1 << h) - 1; i < (1 << (h + 1)) - 1; i++) {
                sb.append(tree[i]).append(" ");
            }
            sb.append('\n');
        }
        return sb.toString();
    }

    public static enum QueryFunctions{
        SUM((u, v) -> u + v, 0),
        // PRODUCT((u, v) -> u * v, 1),
        MAX((u, v) -> u > v ? u : v, Long.MIN_VALUE),
        MIN((u, v) -> u < v ? u : v, Long.MAX_VALUE),
        // GCD((u, v) -> gcd(u, v), 0),
        // LCM((u, v) -> lcm(u, v), 1),
        ;
        private final LongBinaryOperator queryFunction;
        private final long idElm;
        private QueryFunctions(LongBinaryOperator queryFunction, long idElm){
            this.queryFunction = queryFunction;
            this.idElm = idElm;
        }
        public LongBinaryOperator getQueryFunction(){
            return queryFunction;
        }
        public long getIdElm(){
            return idElm;
        }
    }
    public static enum UpdateFunctions{
        ADD((u, v) -> u + v, (u, v) -> u + v, (u, l) -> u * l, 0),
        SUB((u, v) -> u - v, (u, v) -> u + v, (u, l) -> u * l, 0),
        // MUL((u, v) -> u * v, (u, v) -> u * v, (u, l) -> u, 1),
        REWRITE((u, v) -> v, (u, v) -> v, (u, l) -> u, Long.MIN_VALUE + 1),
        ;
        private final LongBinaryOperator updateFunction;
        private final LongBinaryOperator mergeLazyFunction;
        private final BiFunction<Long, Integer, Long> collapseUpdateFunction;
        private final long defaultLazyValue;
        private UpdateFunctions(LongBinaryOperator updateFunction, LongBinaryOperator mergeLazyFunction, BiFunction<Long, Integer, Long> collapseUpdateFunction, long defaultLazyValue){
            this.updateFunction = updateFunction;
            this.mergeLazyFunction = mergeLazyFunction;
            this.collapseUpdateFunction = collapseUpdateFunction;
            this.defaultLazyValue = defaultLazyValue;
        }
        public LongBinaryOperator getUpdateFunction(){
            return updateFunction;
        }
        public LongBinaryOperator getMergeLazyFunction(){
            return mergeLazyFunction;
        }
        public BiFunction<Long, Integer, Long> getCollapseUpdateFunction(){
            return collapseUpdateFunction;
        }
        public long getDefaultLazyValue(){
            return defaultLazyValue;
        }
    }
    public static LazySegmentTree create(long[] t, QueryFunctions queryFunctionCode, UpdateFunctions updateFunctionCode){
        LongBinaryOperator operator = queryFunctionCode.getQueryFunction();
        long idElm = queryFunctionCode.getIdElm();
        LongBinaryOperator updateFunction = updateFunctionCode.getUpdateFunction();
        LongBinaryOperator mergeLazyFunction = updateFunctionCode.getMergeLazyFunction();
        BiFunction<Long, Integer, Long> collapseUpdateFunction = updateFunctionCode.getCollapseUpdateFunction();
        long defaultLazyValue = updateFunctionCode.getDefaultLazyValue();
        return new LazySegmentTree(t, operator, idElm, updateFunction, mergeLazyFunction, collapseUpdateFunction, defaultLazyValue);
    }
}

class LongQueue {
    private long[] a;
    private int head = 0, tail = 0;

    public LongQueue(int max) {
        a=new long[max+2];
    }
    public void addLast(long x) {
        a[tail++]=x;
    }
    public long pollFirst(){
        if (tail == head) {
            try { throw new Exception("no elements."); }
            catch (Exception e) { e.printStackTrace(); }
        }
        return a[head++];
    }
    public long pollLast() {
        if (tail == head) {
            try { throw new Exception("no elements."); }
            catch (Exception e) { e.printStackTrace(); }
        }
        return a[--tail];
    }
    public long getFirst() {
        return a[head];
    }
    public long getLast() {
        return a[tail - 1];
    }
    public int size() {
        return tail - head;
    }
    public void init() {
        head = tail = 0;
    }
}

class LongUtil {
    public static long min(long... a) {
        long ret = Const.LINF;
        for (long c : a) ret = Math.min(ret, c);
        return ret;
    }

    public static long max(long... a) {
        long ret = -Const.LINF;
        for (long c : a) ret = Math.max(ret, c);
        return ret;
    }

    /**
     * Caluculate the ceil of a/b. Returns the smallest integer greater than or
     * equal to a/b while 'a/b' rounds fractional parts to ZERO.
     *
     * @param a
     * @param b
     * @return the smallest integer greater than or equal to a/b
     */
    public static long cld(long a, long b) {
        if (a > 0 && b > 0) return (a + b - 1) / b;
        else if (a < 0 && b < 0) return (a + b + 1) / b;
        else return a / b;
    }

    /**
     * Caluculate the floor of a/b. Returns the largest integer less than or equal
     * to a/b while 'a/b' rounds fractional parts to ZERO.
     *
     * @param a
     * @param b
     * @return the largest integer less than or equal to a/b
     */
    public static long fld(long a, long b) {
        if (a <= 0 && b > 0) return (a - b + 1) / b;
        else if (a > 0 && b <= 0) return (a - b - 1) / b;
        else return a / b;
    }

    public static long fold(LongBinaryOperator func, long a, long... b) {
        long ret = a;
        for (long c : b) ret = func.applyAsLong(ret, c);
        return ret;
    }
}

class MathUtil{
    /**
     * Enumarate primes equal to or less than n.
     * @param n
     * @return {@code ArrayList} that holds primes.
     */
    public static ArrayList<Integer> eratosthenes(int n) {
        int[] div = eratosthenesDivisors(n);
        ArrayList<Integer> result = new ArrayList<>();
        for (int i = 2; i <= n; i++) if (div[i] == i) result.add(i);
        return result;
    }
    /**
     * execute eratosthenes's prime-enumerate algorithm. a[i] holds the greatest
     * divisor of i. if a[i] = i, i is a prime number. This arrary enables you to
     * prime-factorize in O(log n) time.
     * @param n
     * @return divisor array.
     */
    public static int[] eratosthenesDivisors(int n) {
        int[] divisors = new int[n + 1];
        if (n <= 0) return null;
        for (int i = 1; i <= n; i++) {
            if ((i & 1) != 0) divisors[i] = i;
            else divisors[i] = 2;
        }
        for (int i = 3; i <= n; i += 2) {
            if (divisors[i] == i) {
                for (long j = (long) i * i; j <= n; j += i << 1) divisors[(int) j] = i;
            }
        }
        return divisors;
    }

    /**
     * Caluculate prime-factorization in O(sqrt(n)) time.
     * @param n
     * @return {@code HashMap} of {prime: index}
     */
    public static HashMap<Long, Integer> primeFactorization(long n) {
        HashMap<Long, Integer> primes = new HashMap<>();
        for (long p = 2; p * p <= n; p++) {
            int q = 0;
            while (n % p == 0) {
                n /= p;
                q++;
            }
            if (q > 0) primes.put(p, q);
        }
        if (n > 1) primes.put(n, 1);
        return primes;
    }

    private static HashMap<Long, Integer> lcm(HashMap<Long, Integer> amap, HashMap<Long, Integer> bmap) {
        if (amap.size() < bmap.size()) return lcm(bmap, amap);
        HashMap<Long, Integer> lcm = amap;
        for (Map.Entry<Long, Integer> e : bmap.entrySet()) {
            long prime = e.getKey();
            if (lcm.containsKey(prime)) lcm.put(prime, Math.max(lcm.get(prime), e.getValue()));
            else lcm.put(prime, e.getValue());
        }
        return lcm;
    }
    private static HashMap<Long, Integer> lcm(HashMap<Long, Integer> amap, long b) {
        HashMap<Long, Integer> bmap = primeFactorization(b);
        return lcm(amap, bmap);
    }
    public static HashMap<Long, Integer> lcm(long... a) {
        HashMap<Long, Integer> amap = new HashMap<>();
        for (long c : a) amap = lcm(amap, c);
        return amap;
    }
    public static long unsafeLCM(long a, long b) {
        return a * b / gcd(a, b);
    }

    /**
     * Caluculate the GCD of (a, b)/
     *
     * @param a first value
     * @param b second value
     * @return GCD(a, b)
     */
    public static long gcd(long a, long b) {
        if (a < b) return gcd(b, a);
        if (b == 0) return a;
        if (a == 0) return b;
        long r = a % b;
        while (r != 0) {
            a = b;
            b = r;
            r = a % b;
        }
        return b;
    }
    public static long gcd(long... a){
        long gcd = 0;
        for (long c:a) gcd = gcd(gcd, c);
        return gcd;
    }
    /**
     * Return one of the solutions to {@code ax+by=gcd(a, b)}.
     * @return {@code x}, {@code y}, {@code gcd(a, b)}.
     * @param a a of ax+by=gcd(a, b).
     * @param b b of ax+by=gcd(a, b). class ReferenceLong is a reference type of long.
     */
    public static long[] extGCD(long a, long b) {
        ReferenceLong x = new ReferenceLong();
        ReferenceLong y = new ReferenceLong();
        long[] ret = new long[3];
        ret[2] = extGCD(a, b, x, y);
        ret[0] = x.v;
        ret[1] = y.v;
        return ret;
    }
    private static long extGCD(long a, long b, ReferenceLong x, ReferenceLong y) {
        if (b == 0) {
            x.v = 1;
            y.v = 0;
            return a;
        }
        long d = extGCD(b, a % b, y, x);
        y.v -= a / b * x.v;
        return d;
    }
    private static class ReferenceLong {
        long v = 0;
    }
}

class MinimumSpanningTree{
    public static Edge[] kruskal(int n, Edge[] edges){
        UnionFindTree t = new UnionFindTree(n);
        Queue<Edge> pq = new PriorityQueue<>((u, v) -> Long.compare(u.cost, v.cost));
        for(Edge e:edges) pq.add(e);
        Edge[] ret = new Edge[n-1];
        int index = 0;
        while(pq.size() > 0 && index < n){
            Edge e=pq.poll();
            if(!t.isSame(e.from, e.to)){
                t.unite(e.from, e.to);
                ret[index++]=e;
            }
        }
        return ret;
    }
    public static Edge[] prim(int n, Node[] nodes){
        HashSet<Integer> connected = new HashSet<>();
        connected.add(0);
        Queue<Edge> pq = new PriorityQueue<>((u, v) -> Long.compare(u.cost, v.cost));
        for(Edge e: nodes[0].edges) pq.add(e);
        Edge[] ret = new Edge[n-1];
        int index = 0;
        while (pq.size() > 0 && connected.size() < n) {
            Edge e = pq.poll();
            for (int i = 0; i < 2; i++) {
                int v = i == 0 ? e.from : e.to;
                if (!connected.contains(v)) {
                    ret[index++] = e;
                    connected.add(v);
                    for(Edge edge: nodes[v].edges) {
                        if (!connected.contains(edge.from) || !connected.contains(edge.to)) pq.add(edge);
                    }
                }
            }
        }
        return ret;
    }
}

class ModUtil {
    private static final long MOD = Const.MOD;

    public static long mod(long a) {
        a %= MOD;
        if (a < 0) a += MOD;
        return a;
    }

    public static long add(long... a) {
        long ret = 0;
        for (long c : a) ret += c;
        ret %= MOD;
        if (ret < 0) ret += MOD;
        return ret;
    }

    public static long mul(long... a) {
        long ret = 1;
        for (long c : a) ret = (ret * c) % MOD;
        return ret;
    }

    public static long div(long a, long... b) {
        long ret = a;
        for (long c : b) ret = (ret * inv(c)) % MOD;
        return ret;
    }

    /**
     * Caluculate the value b s.t. a*b mod MOD = 1.
     *
     * @param a
     * @return inverse of a
     */
    public static long inv(long a) {
        long b = MOD;
        long u = 1, v = 0;
        while (b >= 1) {
            long t = a / b;
            a -= t * b;
            long tmp1 = a; a = b; b = tmp1;
            u -= t * v;
            long tmp2 = u; u = v; v = tmp2;
        }
        u %= MOD;
        return u >= 0 ? u : u + MOD;
    }

    /**
     * Caluculate the combination nCr.
     *
     * @param n left
     * @param r right
     * @return nCr
     */
    public static long comb(long n, long r) {
        if (n < r) return 0;
        r = Math.min(r, n - r);
        long res = 1;
        for (long d = 1; d <= r; d++) res = div(mul(res, n--), d);
        return res;
    }

    public static long[] fact(int n) {
        long[] fact = new long[n + 1];
        for (int i = 0; i <= n; i++) {
            if (i <= 1) fact[i] = 1;
            else fact[i] = mul(fact[i - 1], i);
        }
        return fact;
    }

    public static long[] powarr(long a, int n) {
        long[] ret = new long[n + 1];
        for (int i = 0; i <= n; i++) {
            if (i == 0) ret[i] = 1;
            else ret[i] = mul(ret[i - 1], a);
        }
        return ret;
    }

    /**
     * Caluculate a^b (mod {@code MOD}) in O(log b) time.
     *
     * @param a base
     * @param b index
     * @return a^b (mod {@code MOD})
     */
    public static long pow(long a, long b) {
        if (b == 0) return 1;
        long half = pow(a, b >> 1);
        if ((a & 1) == 0) return mul(half, half);
        return mul(a, half, half);
    }
}

class Node{
    public int id;
    public ArrayList<Edge> edges;
    public long w;
    public int in;

    public Node(int id){
        this.id=id;
        this.edges = new ArrayList<Edge>();
    }
    public Node(int id, long w){
        this.id = id;
        this.w = w;
        this.edges = new ArrayList<>();
    }
    @Override public boolean equals(Object o){
        if(this == o) return true;
        if(! (o instanceof Node)) return false;
        Node n=(Node) o;
        return n.id == id;
    }
    @Override public int hashCode(){
        return id;
    }
}

@SuppressWarnings("unchecked")
class PolyLazySegmentTree<T, U>{
    private T[] tree;
    private U[] lazy;
    private T idElm;
    private U defaultLazyValue;
    private BiFunction<T, T, T> operator;
    private BiFunction<T, U, T> updateFunction;
    private BiFunction<U, U, U> mergeLazyFunction;
    private BiFunction<U, Integer, U> collapseUpdateFunction;
    private int size;
    private int leafs;
    private int height;
    private int baseOfLeaf;

    public PolyLazySegmentTree(T[] t, BiFunction<T, T, T> operator, T idElm, BiFunction<T, U, T> updateFunction, BiFunction<U, U, U> mergeLazyFunction , BiFunction<U, Integer, U> collapseUpdateFunction, U defaultLazyValue){
        int n = t.length;
        this.operator = operator;
        this.idElm = idElm;
        this.updateFunction = updateFunction;
        this.mergeLazyFunction = mergeLazyFunction;
        this.collapseUpdateFunction = collapseUpdateFunction;
        this.defaultLazyValue = defaultLazyValue;
        this.height = minimumPowerOfTwo(n);
        this.leafs = 1 << this.height;
        this.baseOfLeaf = this.leafs - 1;
        this.size = 2 * this.leafs - 1;
        this.lazy = (U[]) new Object[this.size];
        this.tree = (T[]) new Object[this.size];
        for(int i = size - 1; i >= 0; i--) {
            if(i >= baseOfLeaf + n) {
                this.tree[i] = this.idElm;
            } else if(isLeaf(i)) {
                this.tree[i] = t[i - baseOfLeaf];
            } else{
                this.tree[i] = operator.apply(this.tree[left(i)], this.tree[right(i)]);
            }
        }
    }

    public void applyForSegment(int l, int r, U v){
        applyForSegment(new Range(l, r), 0, new Range(0, leafs), v);
    }
    private T applyForSegment(Range queryRange, int k, Range treeRange, U v){
        evaluate(k, treeRange);
        if(queryRange.crosses(treeRange)) {
            if(queryRange.contains(treeRange)) {
                lazy[k] = mergeLazyFunction.apply(lazy[k], v);
                return updateFunction.apply(tree[k], collapseUpdateFunction.apply(lazy[k], treeRange.length()));
            } else {
                T left = applyForSegment(queryRange, left(k), treeRange.leftHalf(), v);
                T right = applyForSegment(queryRange, right(k), treeRange.rightHalf(), v);
                return tree[k] = operator.apply(left, right);
            }
        } else{
            return tree[k];
        }
    }
    public void applyForPoint(int i, U v){
        tree[baseOfLeaf + i] = updateFunction.apply(tree[baseOfLeaf + i], collapseUpdateFunction.apply(v, 1));
    }

    public T query(int l, int r){
        return query(new Range(l, r), 0, new Range(0, leafs));
    }
    private T query(Range queryRange, int k, Range treeRange){
        evaluate(k, treeRange);
        if(!queryRange.crosses(treeRange)){
            return idElm;
        } else if(queryRange.contains(treeRange)){
            return tree[k];
        } else{
            T left = query(queryRange, left(k), treeRange.leftHalf());
            T right = query(queryRange, right(k), treeRange.rightHalf());
            return operator.apply(left, right);
        }
    }
    private void evaluate(int k, Range r){
        if(lazy[k] != defaultLazyValue) {
            if(!isLeaf(k)){
                lazy[left(k)] = mergeLazyFunction.apply(lazy[left(k)], lazy[k]);
                lazy[right(k)] = mergeLazyFunction.apply(lazy[right(k)], lazy[k]);
            }
            tree[k] = updateFunction.apply(tree[k], collapseUpdateFunction.apply(lazy[k], r.length()));
            lazy[k] = defaultLazyValue;
        }
    }
    private int minimumPowerOfTwo(int n){
        int i = 0;
        while(1 << ++i < n);
        return i;
    }
    private boolean isLeaf(int i){
        return i >= baseOfLeaf;
    }
    private int left(int k){
        return 2 * k + 1;
    }
    private int right(int k){
        return 2 * k + 2;
    }

    public String toString(){
        StringBuilder sb = new StringBuilder();
        for(int h = 0; h <= height; h++) {
            for(int i = (1 << h) - 1; i < (1 << (h + 1)) - 1; i++) {
                sb.append(tree[i]).append(" ");
            }
            sb.append('\n');
        }
        return sb.toString();
    }
}

class Range{
    public static final int MAX = +Const.IINF;
    public static final int MIN = -Const.IINF;
    public static final Range EMPTY = new Range(MAX, MAX);
    public static final Range WHOLE = new Range(MIN, MAX);

    public int left;
    public int right;

    public Range(int left, int right){
        if(left >= right){
            this.left = EMPTY.left;
            this.right = EMPTY.right;
        } else{
            this.left = left;
            this.right = right;
        }
    }
    public boolean crosses(Range r){
        return this.left < r.right && r.left < this.right;
    }
    public boolean contains(Range r){
        if(this.isEmpty()) return false;
        if(r.isEmpty()) return true;
        return this.left <= r.left && r.right <= this.right;
    }
    public Range leftHalf(){
        if(this.isEmpty()) return EMPTY;
        return new Range(left, (left + right) >> 1);
    }
    public Range rightHalf(){
        if(this.isEmpty()) return EMPTY;
        return new Range((left + right) >> 1, right);
    }
    public int length(){
        return right - left;
    }
    public Range intersection(Range r){
        if(!this.crosses(r)) return EMPTY;
        return new Range(Math.max(this.left, r.left), Math.min(this.right, r.right));
    }
    public ArrayList<Range> union(Range r){
        ArrayList<Range> union = new ArrayList<>();
        if(this.isEmpty()){
            union.add(r);
        } else if(r.isEmpty()){
            union.add(this);
        } else if(this.crosses(r)){
            union.add(new Range(Math.min(this.left, r.left), Math.max(this.right, r.right)));
        } else {
            if(this.left < r.left){
                union.add(this);
                union.add(r);
            } else{
                union.add(r);
                union.add(this);
            }
        }
        return union;
    }
    public boolean isEmpty(){
        return this.equals(EMPTY);
    }
    public boolean nonEmpty(){
        return !this.isEmpty();
    }

    public static boolean crosses(Range r1, Range r2){
        return r1.crosses(r2);
    }
    public static Range leftHalf(Range r){
        return r.leftHalf();
    }
    public static Range rightHalf(Range r){
        return r.rightHalf();
    }
    public static int length(Range r){
        return r.length();
    }
    public static Range interSection(Range... rs){
        Range ret = WHOLE;
        for(Range r: rs) ret = ret.intersection(r);
        return ret;
    }
    public static ArrayList<Range> union(Range... rs){
        sort(rs, (u, v) -> Integer.compare(u.left, v.left));
        ArrayList<Range> union = new ArrayList<>();
        Range now = null;
        for(Range r: rs){
            if(r.isEmpty()) break;
            if(isNull(now)){
                now = r;
            } else{
                if(r.left <= now.right){
                    now.right = r.right;
                } else{
                    union.add(now);
                    now = r;
                }
            }
        }
        if(!isNull(now) && !now.equals(EMPTY)) union.add(now);
        if(union.isEmpty()) union.add(EMPTY);
        return union;
    }
    public static boolean isEmpty(Range r){
        return r.isEmpty();
    }
    public static boolean nonEmpty(Range r){
        return r.nonEmpty();
    }

    @Override
    public boolean equals(Object o){
        if(this == o) return true;
        if(!(o instanceof Range)) return false;
        Range r = (Range) o;
        return this.left == r.left && this.right == r.right;
    }
    @Override
    public int hashCode(){
        return hash(left, right);
    }
    @Override
    public String toString(){
        return "["+left+", "+right+")";
    }
}

class RollingHash {
    private static final long mod = (1l << 61) - 1;
    private static final long mask31 = (1l << 31) - 1;
    private static final long mask30 = (1l << 30) - 1;
    private long base;
    private long[] pow;
    private int length;
    private long[] hash; // hash[i] is the hash of substring[0, i). (i = 0, 1, ..., length)

    public RollingHash(char[] ch) {
        this.length = ch.length;
        Random r = new Random(System.currentTimeMillis());
        do this.base = r.nextLong(); while (this.base >= mod - 1 || this.base <= 6000);
        this.pow = new long[this.length + 1];
        for (int i = 0; i <= this.length; i++) {
            if (i == 0) this.pow[i] = 1;
            else this.pow[i] = mod(mul(this.pow[i - 1], this.base));
        }
        this.hash = new long[this.length + 1];
        for(int i = 0; i < this.length; i++) this.hash[i + 1] = mod(mul(this.hash[i], this.base) + ch[i] + 1);
    }
    public long hash(int begin, int end) {
        long ret = hash[end] - mod(mul(hash[begin], pow[end - begin]));
        if (ret < 0) ret += mod;
        return ret;
    }

    // calc a*b mod 2^61-1 without overflow using the fact that 2^61 = 1 mod 2^61-1.
    private long mul(long a, long b) {
        // au is upper 30(=61-31) bits of a, ad is lower 31 bits of a.
        // bu is upper 30(=61-31) bits of b, bd is lower 31 bits of b.
        // => a*b = (au*2^31 + ad)*(bu*2^31 + bd) = au*bu*2^62 + (au*bd + ad*bu)*2^31 + ad*bd.
        long au = a >> 31, ad = a & mask31;
        long bu = b >> 31, bd = b & mask31;
        // 1. au*bu*2^62 equiv to au*bu*2 <= 2*(2^30-1)*(2^30-1)
        // 2. m := au*bd + ad*bu <= 2*(2^30-1)*(2^31-1)
        // mu is upper 31(=61-30) bits of m, md is lower 30 bits of m.
        // m*2^31 = midu*2^61 + midd*2^31 = midu + midd*2^31 <= 2^61+2^31
        // 3. ad*bd <= (2^31-1)*(2^31-1)
        // => (au*bu*2)+(mu+md*2^31)+(ad*bd) < L_MAX
        long m = au * bd + ad * bu;
        long mu = m >> 30, md = m & mask30;
        return ((au * bu) << 1) + (mu + (md << 31)) + (ad * bd);
    }
    private long mod(long l) {
        l = (l & mod) + (l >> 61);
        while (l > mod) l -= mod;
        return l;
    }
}

class Search {
    // return the distance from 's' to other vertices as an array.
    public static int[] bfs(ArrayList<Integer>[] nodes, int s) {
        IntQueue q = new IntQueue(nodes.length);
        q.addLast(s);
        int n = nodes.length;
        int[] d = new int[n];
        fill(d, -1);
        d[s] = 0;
        while(q.size() > 0){
            int now = q.pollFirst();
            for(int next: nodes[now]){
                if(d[next] < 0){
                    d[next] = d[now] + 1;
                    q.addLast(next);
                }
            }
        }
        return d;
    }

    /**
     * return the shortest path from 's' to 't' as an array.
     * [s, a1, a2, ..., ak, t] => distance = array.length-1
     * if NO path from 's' to 't' exists, returns NULL.
     */
    public static int[] bfs(ArrayList<Integer>[] nodes, int s, int t) {
        IntQueue q = new IntQueue(nodes.length + 1);
        q.addLast(s);
        int n = nodes.length;
        int[] d = new int[n];
        int[] prev = new int[n];
        fill(d, -1);
        d[s] = 0;
        while(q.size() > 0){
            int now = q.pollFirst();
            for(int next: nodes[now]){
                if(d[next] < 0){
                    d[next] = d[now] + 1;
                    prev[next] = now;
                    q.addLast(next);
                }
            }
        }
        if(d[t] < 0) return null;
        int now = t;
        int[] path = new int[d[t] + 1];
        for (int i = 0; i <= d[t]; i++) {
            path[d[t] - i] = now;
            now = prev[now];
        }
        return path;
    }

    public static int[] _01bfs(Node[] nodes, int s){
        ArrayDeque<Integer> dq = new ArrayDeque<>();
        dq.add(s);
        int n = nodes.length;
        int[] d = new int[n];
        boolean[] visited=new boolean[n];
        fill(d, Const.IINF);
        d[s] = 0;
        while (dq.size() > 0) {
            int now = dq.pollFirst();
            if(visited[now]) continue;
            visited[now] = true;
            for (Edge e: nodes[now].edges) {
                int next = e.to;
                int cost = (int) e.cost;
                if (d[next] > d[now]) {
                    if (cost == 0) dq.addFirst(next);
                    else dq.addLast(next);
                    d[next] = d[now] + cost;
                }
            }
        }
        return d;
    }
}

class SegmentTree{
    private long[] tree;
    private long idElm;
    private LongBinaryOperator operator;
    private int size;
    private int leafs;
    private int height;
    private int baseOfLeaf;

    public SegmentTree(long[] t, long idElm, LongBinaryOperator operator){
        int n = t.length;
        this.idElm = idElm;
        this.height = minimumPowerOfTwo(n);
        this.leafs = 1 << this.height;
        this.baseOfLeaf = this.leafs - 1;
        this.size = 2 * this.leafs - 1;
        this.tree = new long[this.size];
        for(int i = size - 1; i >= 0; i--) {
            if(i >= baseOfLeaf + n) this.tree[i] = this.idElm;
            else if(isLeaf(i)) this.tree[i] = t[i - baseOfLeaf];
            else this.tree[i] = operator.applyAsLong(this.tree[left(i)], this.tree[right(i)]);
        }
    }
    public void update(int i, int v){
        int index = i + baseOfLeaf;
        int parent = index;
        tree[index] = v;
        while(parent > 0){
            parent = (parent - 1) >> 1;
            tree[parent] = operator.applyAsLong(tree[left(parent)], tree[right(parent)]);
        }
    }
    public long query(int a, int b){
        return query(new Range(a, b), 0, new Range(0, leafs));
    }
    private long query(Range queryRange, int k, Range treeRange){
        if(!queryRange.crosses(treeRange)){
            return idElm;
        } else if(queryRange.contains(treeRange)){
            if(isLeaf(k)) return tree[k];
            else return tree[k] = operator.applyAsLong(tree[left(k)], tree[right(k)]);
        } else{
            long left=query(queryRange, left(k), treeRange.leftHalf());
            long right=query(queryRange, right(k), treeRange.rightHalf());
            return operator.applyAsLong(left, right);
        }
    }
    private int minimumPowerOfTwo(int n){
        int i = 0;
        while(1 << ++i < n);
        return i;
    }
    private boolean isLeaf(int i){
        return i >= baseOfLeaf;
    }
    private int left(int k){
        return 2 * k + 1;
    }
    private int right(int k){
        return 2 * k + 2;
    }
    public String toString(){
        StringBuilder sb = new StringBuilder();
        for(int h = 0; h <= height; h++){
            for(int i = (1 << h) - 1; i < (1 << (h + 1)) - 1; i++){
                sb.append(tree[i]).append(' ');
            }
            sb.append('\n');
        }
        return sb.toString();
    }
}

class TopologicalSort{
    public static int[] topologicalSort(Node[] nodes){
        int n = nodes.length;
        int[] ret = new int[n];
        IntQueue zeros = new IntQueue(n);
        for(Node node: nodes) if(node.in == 0) zeros.addLast(node.id);
        int index = 0;
        while(zeros.size() > 0){
            int v = zeros.pollFirst();
            for (Edge e: nodes[v].edges) if(--nodes[e.to].in == 0) zeros.addLast(e.to);
            ret[index++]=v;
        }
        if(index < n) return null;
        return ret;
    }

    // for example (n=9)
    // [1, 8] -> [2, 5, 6] -> [3, 7] -> [4] -> [9]
    // => length:5
    public static int shortest(Node[] nodes){
        int n = nodes.length;
        int ret = 0;
        IntQueue zeros = new IntQueue(n);
        for(Node node: nodes) if(node.in == 0) zeros.addLast(node.id);
        int num = zeros.size();
        while(zeros.size() > 0){
            int size = zeros.size();
            while(size > 0){
                int v = zeros.pollFirst();
                size--;
                for(Edge e: nodes[v].edges){
                    if(--nodes[e.to].in == 0){
                        zeros.addLast(e.to);
                        num++;
                    }
                }
            }
            ret++;
        }
        if(num < n) return -1;
        return ret;
    }
}

class UnionFindTree {
    private int[] parent;
    private int[] rank;
    private int[] size;
    private int groups;
    public UnionFindTree(int n){
        this.parent = new int[n];
        this.rank = new int[n];
        this.size = new int[n];
        this.groups = n;
        fill(this.size, 1);
        for(int i = 0; i < n; i++) parent[i] = i;
    }
    public int root(int x){
        if(parent[x] == x) return x;
        return parent[x] = root(parent[x]);
    }
    public boolean isSame(int x, int y){
        return root(x) == root(y);
    }
    public void unite(int x, int y){
        int xr = root(x);
        int yr = root(y);
        if(xr == yr) return;
        if(rank[xr] < rank[yr]){
            parent[xr] = yr;
            size[yr] += size[xr];
        }
        else{
            parent[yr] = xr;
            size[xr] += size[yr];
            if(rank[xr] == rank[yr]) rank[xr]++;
        }
        groups--;
    }
    public int size(int x){
        return size[root(x)];
    }
    public int groups(){
        return groups;
    }
}