Each New Year Timofey and his friends cut down a tree of n vertices and bring it home. After that they paint all the n its vertices, so that the i-th vertex gets color ci.Now it's time for Timofey birthday, and his mother asked him to remove the tree. Timofey removes the tree in the following way: he takes some vertex in hands, while all the other vertices move down so that the tree becomes rooted at the chosen vertex. After that Timofey brings the tree to a trash can.Timofey doesn't like it when many colors are mixing together. A subtree annoys him if there are vertices of different color in it. Timofey wants to find a vertex which he should take in hands so that there are no subtrees that annoy him. He doesn't consider the whole tree as a subtree since he can't see the color of the root vertex.A subtree of some vertex is a subgraph containing that vertex and all its descendants.Your task is to determine if there is a vertex, taking which in hands Timofey wouldn't be annoyed.

The first line contains single integer n (2 ≤ n ≤ 105) — the number of vertices in the tree. Each of the next n - 1 lines contains two integers u and v (1 ≤ u, v ≤ n, u ≠ v), denoting there is an edge between vertices u and v. It is guaranteed that the given graph is a tree. The next line contains n integers c1, c2, ..., cn (1 ≤ ci ≤ 105), denoting the colors of the vertices.

Print "NO" in a single line, if Timofey can't take the tree in such a way that it doesn't annoy him. Otherwise print "YES" in the first line. In the second line print the index of the vertex which Timofey should take in hands. If there are multiple answers, print any of them.

package main

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

type UnionFind struct {
	ranks   []int
	parents []int
	counts  []int
}

func NewUnionFind(sz int) *UnionFind {
	ra := make([]int, sz)
	pa := make([]int, sz)
	co := make([]int, sz)
	for i := 0; i < sz; i++ {
		ra[i] = 1
		co[i] = 1
		pa[i] = i
	}
	uf := UnionFind{
		ranks:   ra,
		parents: pa,
		counts:  co,
	}
	return &uf
}

func (this *UnionFind) FindParent(x int) int {
	if x == this.parents[x] {
		return x
	} else {
		this.parents[x] = this.FindParent(this.parents[x])
		return this.parents[x]
	}
}
func (this *UnionFind) IsSame(x int, y int) bool {
	return this.FindParent(x) == this.FindParent(y)
}
func (this *UnionFind) Unite(x int, y int) {
	px := this.FindParent(x)
	py := this.FindParent(y)
	if px == py {
		return
	}
	if this.ranks[px] > this.ranks[py] {
		this.parents[py] = px
		this.counts[px] += this.counts[py]
	} else {
		this.parents[px] = py
		this.counts[py] += this.counts[px]
		if this.ranks[px] == this.ranks[py] {
			this.ranks[py] += 1
		}
	}
}
func (this *UnionFind) GroupSize(x int) int {
	return this.counts[this.FindParent(x)]
}

var sc = bufio.NewScanner(os.Stdin)

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

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

	uf := NewUnionFind(n + 1)
	es := make(map[int][]int)

	for i := 0; i < n-1; i++ {
		u := nextInt()
		v := nextInt()
		es[u] = append(es[u], v)
		es[v] = append(es[v], u)
	}

	cs := make([]int, n+1)
	for i := 1; i <= n; i++ {
		c := nextInt()
		cs[i] = c
	}

	for u, vs := range es {
		for _, v := range vs {
			if cs[u] == cs[v] {
				uf.Unite(u, v)
			}
		}
	}

	st := make(map[int]int)
	for i := 1; i <= n; i++ {
		st[uf.FindParent(i)] = 1
	}

	target_v := -1
	for u, vs := range es {
		tmp := make(map[int]int)
		for _, v := range vs {
			tmp[uf.FindParent(v)] = 1
		}
		x := 0
		if uf.GroupSize(u) == 1 {
			x = 1
		}
		if len(st)-x == len(tmp) {
			target_v = u
			break
		}
	}

	if target_v != -1 {
		fmt.Printf("YES\n%d\n", target_v)
	} else {
		fmt.Printf("NO\n")
	}
}

// Author: sighduck
// URL: https://codeforces.com/problemset/problem/763/A

package main

import (
	"bufio"
	"fmt"
	"os"
)

type Edge struct {
	from int
	to   int
}

type QueueItem struct {
	color  int
	vertex int
}

func search(n int, graph [][]int, colors []int, start int) bool {
	queue := []QueueItem{}
	visited := make([]bool, n+1)
	for _, vertex := range graph[start] {
		queue = append(queue, QueueItem{colors[vertex-1], vertex})
		visited[vertex] = true
	}
	for len(queue) > 0 {
		current := queue[0]
		queue = queue[1:]
		if current.color != colors[current.vertex-1] {
			return false
		}
		for _, vertex := range graph[current.vertex] {
			if vertex != start && !visited[vertex] {
				queue = append(queue, QueueItem{current.color, vertex})
				visited[vertex] = true
			}
		}
	}
	return true
}

func Solve(n int, edges []Edge, colors []int) int {
	graph := make([][]int, n+1)
	for _, edge := range edges {
		graph[edge.from] = append(graph[edge.from], edge.to)
		graph[edge.to] = append(graph[edge.to], edge.from)
	}
	for _, edge := range edges {
		if colors[edge.from-1] != colors[edge.to-1] {
			if search(n, graph, colors, edge.from) {
				return edge.from
			} else if search(n, graph, colors, edge.to) {
				return edge.to
			} else {
				return -1
			}
		}
	}
	return 1
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var n int
	fmt.Fscanf(reader, "%d\n", &n)
	edges := make([]Edge, n-1)
	for i := 0; i < n-1; i++ {
		fmt.Fscanf(reader, "%d %d\n", &edges[i].from, &edges[i].to)
	}
	colors := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Fscanf(reader, "%d", &colors[i])
	}

	answer := Solve(n, edges, colors)
	if answer != -1 {
		fmt.Fprintf(writer, "YES\n%d\n", answer)
	} else {
		fmt.Fprintf(writer, "NO\n")
	}
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func I(i ...interface{}) error {
	_, err := fmt.Fscan(r, i...)
	return err
}

func O(o ...interface{}) {
	fmt.Fprint(w, o...)
}

var (
	r *bufio.Reader
	w *bufio.Writer
)

func init() {
	if f, err := os.Open("in.goC"); err == nil {
		r = bufio.NewReader(f)
	} else {
		r = bufio.NewReader(os.Stdin)
	}
	w = bufio.NewWriter(os.Stdout)
}

type Int int64

func main() {
	defer w.Flush()
	var n Int
	for I(&n) == nil {
		solve(n)
	}
}

func solve(n Int) {
	in := make([][2]Int, n)
	for i := Int(0); i < n-1; i++ {
		I(&in[i][0], &in[i][1])
	}
	c := make([]Int, n+1)
	for i := Int(1); i < n+1; i++ {
		I(&c[i])
	}
	cc := make([]Int, n+1)
	var ccc, m Int
	for i := Int(0); i < n-1; i++ {
		if c[in[i][0]] != c[in[i][1]] {
			cc[in[i][0]]++
			cc[in[i][1]]++
			m = in[i][0]
			if cc[m] < cc[in[i][1]] {
				m = in[i][1]
			}
			ccc++
			if cc[m] != ccc {
				O("NO\n")
				return
			}
		}
	}
	if m == 0 {
		m++
	}
	O("YES\n", m, "\n")
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func I(i ...interface{}) error {
	_, err := fmt.Fscan(r, i...)
	return err
}

func O(o ...interface{}) {
	fmt.Fprint(w, o...)
}

var (
	r *bufio.Reader
	w *bufio.Writer
)

func init() {
	if f, err := os.Open("in.goC"); err == nil {
		r = bufio.NewReader(f)
	} else {
		r = bufio.NewReader(os.Stdin)
	}
	w = bufio.NewWriter(os.Stdout)
}

type Int int64

func main() {
	defer w.Flush()
	var n Int
	for I(&n) == nil {
		solve(n)
	}
}

func solve(n Int) {
	in := make([][2]Int, n)
	for i := Int(0); i < n-1; i++ {
		I(&in[i][0], &in[i][1])
	}
	c := make([]Int, n+1)
	for i := Int(1); i < n+1; i++ {
		I(&c[i])
	}
	cc := make([]Int, n+1)
	var ccc Int
	for i := Int(0); i < n-1; i++ {
		if c[in[i][0]] != c[in[i][1]] {
			cc[in[i][0]]++
			cc[in[i][1]]++
			ccc++
		}
	}
	for i := Int(1); i < n+1; i++ {
		if ccc == cc[i] {
			O("YES\n", i, "\n")
			return
		}
	}
	O("NO\n")
}

package main

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

var (
	n    int
	g    [][]int
	c    []int
	memo map[int64]bool
)

func solve() {
	memo = make(map[int64]bool)
	n = readInt()
	g = make([][]int, n)
	for i := 0; i < n; i++ {
		g[i] = make([]int, 0)
	}
	for i := 0; i < n-1; i++ {
		u := readInt() - 1
		v := readInt() - 1
		g[u] = append(g[u], v)
		g[v] = append(g[v], u)
	}
	c = make([]int, n)
	for i := 0; i < n; i++ {
		c[i] = readInt()
	}
	for i := 0; i < n; i++ {
		ok := true
		for _, v := range g[i] {
			if !dfs(v, i, c[v]) {
				ok = false
				break
			}
		}
		if ok {
			fmt.Println("YES")
			fmt.Println(i + 1)
			return
		}
	}
	fmt.Println("NO")
}

func dfs(v int, from int, color int) bool {
	if c[v] != color {
		return false
	}
	key := int64(v)*1<<32 + int64(from)
	if v, ok := memo[key]; ok {
		return v
	}
	res := true
	for _, u := range g[v] {
		if u != from {
			if !dfs(u, v, color) {
				res = false
				break
			}
		}
	}
	memo[key] = res
	return res
}

var scanner *bufio.Scanner

func main() {
	scanner = bufio.NewScanner(os.Stdin)
	const MaxTokenLength = 1024 * 1024
	scanner.Buffer(make([]byte, 0, MaxTokenLength), MaxTokenLength)
	scanner.Split(bufio.ScanWords)
	solve()
}

// IO

func readString() string {
	scanner.Scan()
	return scanner.Text()
}

func readInt() int {
	val, _ := strconv.Atoi(readString())
	return val
}

func readInt64() int64 {
	v, _ := strconv.ParseInt(readString(), 10, 64)
	return v
}

func readIntArray(sz int) []int {
	a := make([]int, sz)
	for i := 0; i < sz; i++ {
		a[i] = readInt()
	}
	return a
}

func readInt64Array(n int) []int64 {
	res := make([]int64, n)
	for i := 0; i < n; i++ {
		res[i] = readInt64()
	}
	return res
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

package main;
import ("fmt"
        "bufio"
        "os"
        )
const (
    MAX_N=1e5+1;
)
type subTree struct{
    valid bool;
    length int;
    color int;//0 neutral -1 invalid
}
func sum(a subTree,b subTree) subTree{
    if a.color==0 {
        return b;
    }
    if b.color==0 {
        return a;
    }
    if a.valid&&b.valid&&a.color==b.color{
        return subTree{true,a.length+b.length,a.color};
    }
    return subTree{false,0,-1};
}
var G [MAX_N][]int;
var col [MAX_N]int;
var T [MAX_N]subTree;
var F [MAX_N]int;
var cnt int;
func update(color int,x int,sign int){
    if color<=0{
        return;
    }
    if sign==1{
        if F[color]==0{
            cnt++;
        }
    }else{
        if x>0&&F[color]==x{
            cnt--;
        }
    }
    F[color]+=sign*x;
    if F[color]<0{
        panic("WTF");
    }
}
func initGraph(n int){
    for i:=0;i<n;i++{
        G[i]=G[i][:0];
    }
}
func add(u int,v int){
    G[u]=append(G[u],v);
    G[v]=append(G[v],u);
}
var ans bool;
var id int;
func dfs(u int,p int){
    //fmt.Println(u+1,F);
    T[u]=subTree{true,0,0};
    for _,v:=range G[u]{
        if v==p{
            continue;
        }

        dfs(v,u);
        T[u]=sum(T[u],T[v]);
    }
    allValid:=true;
    for _,v:=range G[u]{
        if v==p{
            continue;
        }
        if T[v].valid{
            update(T[v].color,T[v].length,-1);
        }else{
            allValid=false;
        }
    }
    update(col[u],1,-1);
    //fmt.Println(u,cnt,F,T[u]);
    if cnt<=1&&allValid {
        ans=true;
        id=u;
    }
    update(col[u],1,+1);
    T[u]=sum(T[u],subTree{true,1,col[u]});
    for _,v:=range G[u]{
        if v==p{
            continue;
        }
        if T[v].valid{
            update(T[v].color,T[v].length,+1);
        }
    }
}
func main(){
    in := bufio.NewReader(os.Stdin);
    var n int;
    for true{
        if items,_:=fmt.Fscanf(in, "%d\n", &n);items!=1{
            break;
        }
        ans=false;
        initGraph(n);
        cnt=0;
        for i:=0;i<MAX_N;i++{
            F[i]=0;
        }
        for i:=0;i<n-1;i++{
            var u,v int;
            fmt.Fscanf(in, "%d %d\n", &u, &v);
            u--;v--;
            add(u,v);
        }
        for i:=0;i<n;i++{
            var x int;
            fmt.Fscanf(in, "%d\n", &x);
            col[i]=x;
            update(x,1,+1);
        }
        //fmt.Println(F);
        dfs(0,-1);
        if ans{
            fmt.Println("YES");
            fmt.Println(id+1);
        }else{
            fmt.Println("NO");
        }
    }
}

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

func Solve(io *FastIO) {
	N := io.NextInt()

	nodes := make([]Node, N + 1)
	for i := 1; i < N; i++ {
		U := io.NextInt()
		V := io.NextInt()

		nodes[U].next = append(nodes[U].next, &nodes[V])
		nodes[V].next = append(nodes[V].next, &nodes[U])
	}

	for i := 1; i <= N; i++ {
		C := io.NextInt()

		nodes[i].color = C
		nodes[i].group = -1
	}

	grp := 0
	for i := 1; i <= N; i++ {
		if nodes[i].group < 0 {
			FillGroup(&nodes[i], grp)
			grp++
		}
	}

	for i := 1; i <= N; i++ {
		set := make(map[int]bool)
		set[nodes[i].group] = true
		for _, n := range nodes[i].next {
			set[n.group] = true
		}
		if len(set) == grp {
			io.Println("YES")
			io.Println(i)
			return
		}
	}
	io.Println("NO")
}

type Node struct {
	next []*Node
	color int
	group int
}

func FillGroup(node *Node, grp int) {
	node.group = grp
	for _, n := range node.next {
		if n.color == node.color && n.group < 0 {
			FillGroup(n, grp)
		}
	}
}

type FastIO struct {
	reader *bufio.Reader
	writer *bufio.Writer
}

func (io *FastIO) NextChar() byte {
	c, _ := io.reader.ReadByte()
	return c
}

func (io *FastIO) NextInt() int {
	c := io.NextChar()
	for IsSpaceChar(c) {
		c = io.NextChar()
	}
	sgn := 1
	if c == '-' {
		sgn = -1
		c = io.NextChar()
	}
	res := 0
	for !IsSpaceChar(c) {
		res = (res * 10) + int(c - '0')
		c = io.NextChar()
	}
	return sgn * res
}

func (io *FastIO) NextLong() int64 {
	c := io.NextChar()
	for IsSpaceChar(c) {
		c = io.NextChar()
	}
	sgn := int64(1)
	if c == '-' {
		sgn = -1
		c = io.NextChar()
	}
	res := int64(0)
	for !IsSpaceChar(c) {
		res = (res * 10) + int64(c - '0')
		c = io.NextChar()
	}
	return sgn * res
}

func (io *FastIO) NextIntArray(size int) []int {
	return io.NextIntArrayOffset(size, 0)
}

func (io *FastIO) NextIntArrayOffset(size, offset int) []int {
	arr := make([]int, size + offset)
	for i := 0; i < size; i++ {
		arr[i + offset] = io.NextInt()
	}
	return arr
}

func (io *FastIO) NextLongArray(size int) []int64 {
	return io.NextLongArrayOffset(size, 0)
}

func (io *FastIO) NextLongArrayOffset(size, offset int) []int64 {
	arr := make([]int64, size + offset)
	for i := 0; i < size; i++ {
		arr[i + offset] = io.NextLong()
	}
	return arr
}

func (io *FastIO) NextString() string {
	c := io.NextChar()
	for (IsSpaceChar(c)) {
		c = io.NextChar()
	}
	var sb bytes.Buffer
	for !IsSpaceChar(c) {
		sb.WriteByte(c)
		c = io.NextChar()
	}
	return sb.String()
}

func (io *FastIO) NextLine() string {
	c := io.NextChar()
	for (IsSpaceChar(c)) {
		c = io.NextChar()
	}
	var sb bytes.Buffer
	for !IsLineBreakChar(c) {
		sb.WriteByte(c)
		c = io.NextChar()
	}
	return sb.String()
}

func (io *FastIO) Println(args ...interface{}) {
	io.writer.WriteString(fmt.Sprintln(args...))
}

func (io *FastIO) Printf(format string, args ...interface{}) {
	io.writer.WriteString(fmt.Sprintf(format, args...))
}

func (io *FastIO) FlushOutput() {
	io.writer.Flush()
}

func IsSpaceChar(c byte) bool {
	switch c {
	case 0, '\t', '\n', '\r', ' ':
		return true
	default:
		return false
	}
}

func IsLineBreakChar(c byte) bool {
	switch c {
		case 0, '\n', '\r':
			return true
		default:
			return false
	}
}

func main() {
	io := FastIO{reader: bufio.NewReader(os.Stdin), writer: bufio.NewWriter(os.Stdout)}
	Solve(&io)
	io.FlushOutput()
}

package main

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

type UnionFind struct {
	ranks   []int
	parents []int
	counts  []int
}

func NewUnionFind(sz int) *UnionFind {
	ra := make([]int, sz)
	pa := make([]int, sz)
	co := make([]int, sz)
	for i := 0; i < sz; i++ {
		ra[i] = 1
		co[i] = 1
		pa[i] = i
	}
	uf := UnionFind{
		ranks:   ra,
		parents: pa,
		counts:  co,
	}
	return &uf
}

func (this *UnionFind) FindParent(x int) int {
	if x == this.parents[x] {
		return x
	} else {
		this.parents[x] = this.FindParent(this.parents[x])
		return this.parents[x]
	}
}
func (this *UnionFind) IsSame(x int, y int) bool {
	return this.FindParent(x) == this.FindParent(y)
}
func (this *UnionFind) Unite(x int, y int) {
	px := this.FindParent(x)
	py := this.FindParent(y)
	if px == py {
		return
	}
	if this.ranks[px] > this.ranks[py] {
		this.parents[py] = px
		this.counts[px] += this.counts[py]
	} else {
		this.parents[px] = py
		this.counts[py] += this.counts[px]
		if this.ranks[px] == this.ranks[py] {
			this.ranks[py] += 1
		}
	}
}
func (this *UnionFind) GroupSize(x int) int {
	return this.counts[this.FindParent(x)]
}

var sc = bufio.NewScanner(os.Stdin)

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

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

	uf := NewUnionFind(n + 1)
	es := make(map[int][]int)

	for i := 0; i < n-1; i++ {
		u := nextInt()
		v := nextInt()
		es[u] = append(es[u], v)
		es[v] = append(es[v], u)
	}

	cs := make([]int, n+1)
	for i := 1; i <= n; i++ {
		c := nextInt()
		cs[i] = c
	}

	for u, vs := range es {
		for _, v := range vs {
			if cs[u] == cs[v] {
				uf.Unite(u, v)
			}
		}
	}

	st := make(map[int]int)
	for i := 1; i <= n; i++ {
		st[uf.FindParent(i)] = 1
	}

	target_v := -1
	for u, vs := range es {
		tmp := make(map[int]int)
		for v := range vs {
			tmp[uf.FindParent(v)] = 1
		}
		x := 0
		if uf.GroupSize(u) == 1 {
			x = 1
		}
		if len(st)-x == len(tmp) {
			target_v = u
			break
		}
	}

	if target_v != -1 {
		fmt.Printf("YES\n%d\n", target_v)
	} else {
		fmt.Printf("NO\n")
	}
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func I(i ...interface{}) error {
	_, err := fmt.Fscan(r, i...)
	return err
}

func O(o ...interface{}) {
	fmt.Fprint(w, o...)
}

var (
	r *bufio.Reader
	w *bufio.Writer
)

func init() {
	if f, err := os.Open("in.goC"); err == nil {
		r = bufio.NewReader(f)
	} else {
		r = bufio.NewReader(os.Stdin)
	}
	w = bufio.NewWriter(os.Stdout)
}

type Int int64

func main() {
	defer w.Flush()
	var n Int
	for I(&n) == nil {
		solve(n)
	}
}

func solve(n Int) {
	in := make([][2]Int, n)
	for i := Int(0); i < n-1; i++ {
		I(&in[i][0], &in[i][1])
	}
	c := make([]Int, n+1)
	for i := Int(1); i < n+1; i++ {
		I(&c[i])
	}
	cc := make([]Int, n+1)
	var ccc, m Int
	for i := Int(0); i < n-1; i++ {
		if c[in[i][0]] != c[in[i][1]] {
			cc[in[i][0]]++
			cc[in[i][1]]++
			m = in[i][0]
			if m < cc[in[i][1]] {
				m = in[i][1]
			}
			ccc++
			if cc[m] != ccc {
				O("NO\n")
				return
			}
		}
	}
	if m == 0 {
		m++
	}
	O("YES\n", m, "\n")
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func I(i ...interface{}) error {
	_, err := fmt.Fscan(r, i...)
	return err
}

func O(o ...interface{}) {
	fmt.Fprint(w, o...)
}

var (
	r *bufio.Reader
	w *bufio.Writer
)

func init() {
	if f, err := os.Open("in.goC"); err == nil {
		r = bufio.NewReader(f)
	} else {
		r = bufio.NewReader(os.Stdin)
	}
	w = bufio.NewWriter(os.Stdout)
}

type Int int64

func main() {
	defer w.Flush()
	var n Int
	for I(&n) == nil {
		solve(n)
	}
}

func solve(n Int) {
	in := make([][2]Int, n)
	for i := Int(0); i < n-1; i++ {
		I(&in[i][0], &in[i][1])
	}
	c := make([]Int, n+1)
	for i := Int(1); i < n+1; i++ {
		I(&c[i])
	}
	cc := make([]Int, n+1)
	var ccc, m Int
	for i := Int(0); i < n-1; i++ {
		if c[in[i][0]] != c[in[i][1]] {
			cc[in[i][0]]++
			cc[in[i][1]]++
			m = in[i][0]
			if m < cc[in[i][1]] {
				m = in[i][1]
			}
			ccc++
		}
	}
	if m == 0 {
		m++
	} else if cc[m] != ccc {
		O("NO\n")
		return
	}
	O("YES\n", m, "\n")
}

package main;
import ("fmt"
        "bufio"
        "os"
        )
const (
    MAX_N=1e5+1;
)
type subTree struct{
    valid bool;
    length int;
    color int;//0 neutral -1 invalid
}
func sum(a subTree,b subTree) subTree{
    if a.color==0 {
        return b;
    }
    if b.color==0 {
        return a;
    }
    if a.valid&&b.valid&&a.color==b.color{
        return subTree{true,a.length+b.length,a.color};
    }
    return subTree{false,0,-1};
}
var G [MAX_N][]int;
var col [MAX_N]int;
var T [MAX_N]subTree;
var F [MAX_N]int;
var cnt int;
func update(color int,x int,sign int){
    if color<=0{
        return;
    }
    if sign==1{
        if F[color]==0{
            cnt++;
        }
    }else{
        if x>0&&F[color]==x{
            cnt--;
        }
    }
    F[color]+=sign*x;
}
func initGraph(n int){
    for i:=0;i<n;i++{
        G[i]=G[i][:0];
    }
}
func add(u int,v int){
    G[u]=append(G[u],v);
    G[v]=append(G[v],u);
}
var ans bool;
var id int;
func dfs(u int,p int){
    T[u]=subTree{true,0,0};
    for _,v:=range G[u]{
        if v==p{
            continue;
        }

        dfs(v,u);
        T[u]=sum(T[u],T[v]);
        update(T[v].color,T[v].length,-1);
    }

    update(col[u],1,-1);
    //fmt.Println(u,cnt,F,T[u]);
    if cnt==1 {
        ans=true;
        id=u;
    }
    update(col[u],1,+1);
    T[u]=sum(T[u],subTree{true,1,col[u]});
    for _,v:=range G[u]{
        if v==p{
            continue;
        }
        update(T[v].color,T[v].length,+1);
    }
}
func main(){
    in := bufio.NewReader(os.Stdin);
    var n int;
    for true{
        if items,_:=fmt.Fscanf(in, "%d\n", &n);items!=1{
            break;
        }
        ans=false;
        initGraph(n);
        cnt=0;
        for i:=0;i<MAX_N;i++{
            F[i]=0;
        }
        for i:=0;i<n-1;i++{
            var u,v int;
            fmt.Fscanf(in, "%d %d\n", &u, &v);
            u--;v--;
            add(u,v);
        }
        for i:=0;i<n;i++{
            var x int;
            fmt.Fscanf(in, "%d\n", &x);
            col[i]=x;
            update(x,1,+1);
        }
        dfs(0,-1);
        if ans{
            fmt.Println("YES");
            fmt.Println(id+1);
        }else{
            fmt.Println("NO");
        }
    }
}

package main;
import ("fmt"
        "bufio"
        "os"
        )
const (
    MAX_N=1e5+1;
)
type subTree struct{
    valid bool;
    length int;
    color int;//0 neutral -1 invalid
}
func sum(a subTree,b subTree) subTree{
    if a.color==0 {
        return b;
    }
    if b.color==0 {
        return a;
    }
    if a.valid&&b.valid&&a.color==b.color{
        return subTree{true,a.length+b.length,a.color};
    }
    return subTree{false,0,-1};
}
var G [MAX_N][]int;
var col [MAX_N]int;
var T [MAX_N]subTree;
var F [MAX_N]int;
var cnt int;
func update(color int,x int,sign int){
    if color<=0{
        return;
    }
    if sign==1{
        if F[color]==0{
            cnt++;
        }
    }else{
        if x>0&&F[color]==x{
            cnt--;
        }
    }
    F[color]+=sign*x;
    if F[color]<0{
        panic("WTF");
    }
}
func initGraph(n int){
    for i:=0;i<n;i++{
        G[i]=G[i][:0];
    }
}
func add(u int,v int){
    G[u]=append(G[u],v);
    G[v]=append(G[v],u);
}
var ans bool;
var id int;
func dfs(u int,p int){
    //fmt.Println(u+1,F);
    T[u]=subTree{true,0,0};
    for _,v:=range G[u]{
        if v==p{
            continue;
        }

        dfs(v,u);
        T[u]=sum(T[u],T[v]);
    }
    for _,v:=range G[u]{
        if v==p{
            continue;
        }
        if T[v].valid{
            update(T[v].color,T[v].length,-1);
        }
    }
    update(col[u],1,-1);
    //fmt.Println(u,cnt,F,T[u]);
    if cnt<=1&&T[u].valid {
        ans=true;
        id=u;
    }
    update(col[u],1,+1);
    T[u]=sum(T[u],subTree{true,1,col[u]});
    for _,v:=range G[u]{
        if v==p{
            continue;
        }
        if T[v].valid{
            update(T[v].color,T[v].length,+1);
        }
    }
}
func main(){
    in := bufio.NewReader(os.Stdin);
    var n int;
    for true{
        if items,_:=fmt.Fscanf(in, "%d\n", &n);items!=1{
            break;
        }
        ans=false;
        initGraph(n);
        cnt=0;
        for i:=0;i<MAX_N;i++{
            F[i]=0;
        }
        for i:=0;i<n-1;i++{
            var u,v int;
            fmt.Fscanf(in, "%d %d\n", &u, &v);
            u--;v--;
            add(u,v);
        }
        for i:=0;i<n;i++{
            var x int;
            fmt.Fscanf(in, "%d\n", &x);
            col[i]=x;
            update(x,1,+1);
        }
        //fmt.Println(F);
        dfs(0,-1);
        if ans{
            fmt.Println("YES");
            fmt.Println(id+1);
        }else{
            fmt.Println("NO");
        }
    }
}

package main;
import ("fmt"
        "bufio"
        "os"
        )
const (
    MAX_N=1e5+1;
)
type subTree struct{
    valid bool;
    length int;
    color int;//0 neutral -1 invalid
}
func sum(a subTree,b subTree) subTree{
    if a.color==0 {
        return b;
    }
    if b.color==0 {
        return a;
    }
    if a.valid&&b.valid&&a.color==b.color{
        return subTree{true,a.length+b.length,a.color};
    }
    return subTree{false,0,-1};
}
var G [MAX_N][]int;
var col [MAX_N]int;
var T [MAX_N]subTree;
var F [MAX_N]int;
var cnt int;
func update(color int,x int,sign int){
    if color<=0{
        return;
    }
    if sign==1{
        if F[color]==0{
            cnt++;
        }
    }else{
        if x>0&&F[color]==x{
            cnt--;
        }
    }
    F[color]+=sign*x;
    if F[color]<0{
        panic("WTF");
    }
}
func initGraph(n int){
    for i:=0;i<n;i++{
        G[i]=G[i][:0];
    }
}
func add(u int,v int){
    G[u]=append(G[u],v);
    G[v]=append(G[v],u);
}
var ans bool;
var id int;
func dfs(u int,p int){
    //fmt.Println(u+1,F);
    T[u]=subTree{true,0,0};
    for _,v:=range G[u]{
        if v==p{
            continue;
        }

        dfs(v,u);
        T[u]=sum(T[u],T[v]);
    }
    for _,v:=range G[u]{
        if v==p{
            continue;
        }
        if T[v].valid{
            update(T[v].color,T[v].length,-1);
        }
    }
    update(col[u],1,-1);
    //fmt.Println(u,cnt,F,T[u]);
    if cnt==1&&T[u].valid {
        ans=true;
        id=u;
    }
    update(col[u],1,+1);
    T[u]=sum(T[u],subTree{true,1,col[u]});
    for _,v:=range G[u]{
        if v==p{
            continue;
        }
        if T[v].valid{
            update(T[v].color,T[v].length,+1);
        }
    }
}
func main(){
    in := bufio.NewReader(os.Stdin);
    var n int;
    for true{
        if items,_:=fmt.Fscanf(in, "%d\n", &n);items!=1{
            break;
        }
        ans=false;
        initGraph(n);
        cnt=0;
        for i:=0;i<MAX_N;i++{
            F[i]=0;
        }
        for i:=0;i<n-1;i++{
            var u,v int;
            fmt.Fscanf(in, "%d %d\n", &u, &v);
            u--;v--;
            add(u,v);
        }
        for i:=0;i<n;i++{
            var x int;
            fmt.Fscanf(in, "%d\n", &x);
            col[i]=x;
            update(x,1,+1);
        }
        //fmt.Println(F);
        dfs(0,-1);
        if ans{
            fmt.Println("YES");
            fmt.Println(id+1);
        }else{
            fmt.Println("NO");
        }
    }
}


You are given a permutation, $$$p_1, p_2, \ldots, p_n$$$.Imagine that some positions of the permutation contain bombs, such that there exists at least one position without a bomb.For some fixed configuration of bombs, consider the following process. Initially, there is an empty set, $$$A$$$.For each $$$i$$$ from $$$1$$$ to $$$n$$$: Add $$$p_i$$$ to $$$A$$$.  If the $$$i$$$-th position contains a bomb, remove the largest element in $$$A$$$.After the process is completed, $$$A$$$ will be non-empty. The cost of the configuration of bombs equals the largest element in $$$A$$$.You are given another permutation, $$$q_1, q_2, \ldots, q_n$$$.For each $$$1 \leq i \leq n$$$, find the cost of a configuration of bombs such that there exists a bomb in positions $$$q_1, q_2, \ldots, q_{i-1}$$$. For example, for $$$i=1$$$, you need to find the cost of a configuration without bombs, and for $$$i=n$$$, you need to find the cost of a configuration with bombs in positions $$$q_1, q_2, \ldots, q_{n-1}$$$.

The first line contains a single integer, $$$n$$$ ($$$2 \leq n \leq 300\,000$$$). The second line contains $$$n$$$ distinct integers $$$p_1, p_2, \ldots, p_n$$$ ($$$1 \leq p_i \leq n)$$$. The third line contains $$$n$$$ distinct integers $$$q_1, q_2, \ldots, q_n$$$ ($$$1 \leq q_i \leq n)$$$.

Print $$$n$$$ space-separated integers, such that the $$$i$$$-th of them equals the cost of a configuration of bombs in positions $$$q_1, q_2, \ldots, q_{i-1}$$$.

NoteIn the first test:  If there are no bombs, $$$A$$$ is equal to $$$\{1, 2, 3\}$$$ at the end of the process, so the cost of the configuration is $$$3$$$.  If there is one bomb in position $$$1$$$, $$$A$$$ is equal to $$$\{1, 2\}$$$ at the end of the process, so the cost of the configuration is $$$2$$$;  If there are two bombs in positions $$$1$$$ and $$$2$$$, $$$A$$$ is equal to $$$\{1\}$$$ at the end of the process, so the cost of the configuration is $$$1$$$. In the second test:Let's consider the process for $$$i = 4$$$. There are three bombs on positions $$$q_1 = 5$$$, $$$q_2 = 2$$$, and $$$q_3 = 1$$$.At the beginning, $$$A = \{\}$$$.  Operation $$$1$$$: Add $$$p_1 = 2$$$ to $$$A$$$, so $$$A$$$ is equal to $$$\{2\}$$$. There exists a bomb in position $$$1$$$, so we should delete the largest element from $$$A$$$. $$$A$$$ is equal to $$$\{\}$$$.  Operation $$$2$$$: Add $$$p_2 = 3$$$ to $$$A$$$, so $$$A$$$ is equal to $$$\{3\}$$$. There exists a bomb in position $$$2$$$, so we should delete the largest element from $$$A$$$. $$$A$$$ is equal to $$$\{\}$$$.  Operation $$$3$$$: Add $$$p_3 = 6$$$ to $$$A$$$, so $$$A$$$ is equal to $$$\{6\}$$$. There is no bomb in position $$$3$$$, so we do nothing.  Operation $$$4$$$: Add $$$p_4 = 1$$$ to $$$A$$$, so $$$A$$$ is equal to $$$\{1, 6\}$$$. There is no bomb in position $$$4$$$, so we do nothing.  Operation $$$5$$$: Add $$$p_5 = 5$$$ to $$$A$$$, so $$$A$$$ is equal to $$$\{1, 5, 6\}$$$. There exists a bomb in position $$$5$$$, so we delete the largest element from $$$A$$$. Now, $$$A$$$ is equal to $$$\{1, 5\}$$$.  Operation $$$6$$$: Add $$$p_6 = 4$$$ to $$$A$$$, so $$$A$$$ is equal to $$$\{1, 4, 5\}$$$. There is no bomb in position $$$6$$$, so we do nothing. In the end, we have $$$A = \{1, 4, 5\}$$$, so the cost of the configuration is equal to $$$5$$$.

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
)

var seg [2000000]int
var lazy [2000000]int

func segPlus(index, l, r, left, right, plus int) {
	if l == left && r == right {
		lazy[index] += plus
		return
	}
	mid := (l + r) / 2
	if right <= mid {
		segPlus(index*2+1, l, mid, left, right, plus)
	} else if left > mid {
		segPlus(index*2+2, mid+1, r, left, right, plus)
	} else {
		segPlus(index*2+1, l, mid, left, mid, plus)
		segPlus(index*2+2, mid+1, r, mid+1, right, plus)
	}
	leftValue := seg[index*2+1] + lazy[index*2+1]
	rightValue := seg[index*2+2] + lazy[index*2+2]
	if leftValue < rightValue {
		seg[index] = leftValue
	} else {
		seg[index] = rightValue
	}
}

func main() {
	bs, _ := ioutil.ReadAll(os.Stdin)
	reader := bytes.NewReader(bs)
	writer := bytes.NewBuffer(make([]byte, 0, 1000000))
	var n int
	fmt.Fscanf(reader, "%d\n", &n)
	p, q, pos := make([]int, n), make([]int, n), make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Fscanf(reader, "%d", &p[i])
		p[i]--
		pos[p[i]] = i
		if i < n-1 {
			fmt.Fscanf(reader, " ")
		} else {
			fmt.Fscanf(reader, "\n")
		}
	}
	for i := 0; i < n; i++ {
		fmt.Fscanf(reader, "%d", &q[i])
		q[i]--
		if i < n-1 {
			fmt.Fscanf(reader, " ")
		} else {
			fmt.Fscanf(reader, "\n")
		}
	}
	ans := n - 1
	for i := 0; i < n; i++ {
		for seg[0]+lazy[0] >= 0 {
			segPlus(0, 0, n-1, 0, pos[ans], -1)
			ans--
		}
		fmt.Fprintf(writer, "%d ", ans+2)
		segPlus(0, 0, n-1, 0, q[i], 1)
	}
	writer.WriteTo(os.Stdout)
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func readInt(bytes []byte, from int, val *int) int {
	i := from
	sign := 1
	if bytes[i] == '-' {
		sign = -1
		i++
	}
	tmp := 0
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + int(bytes[i]-'0')
		i++
	}
	*val = tmp * sign
	return i
}

func readNum(reader *bufio.Reader) (a int) {
	bs, _ := reader.ReadBytes('\n')
	readInt(bs, 0, &a)
	return
}

func readTwoNums(reader *bufio.Reader) (a int, b int) {
	res := readNNums(reader, 2)
	a, b = res[0], res[1]
	return
}

func readThreeNums(reader *bufio.Reader) (a int, b int, c int) {
	res := readNNums(reader, 3)
	a, b, c = res[0], res[1], res[2]
	return
}

func readNNums(reader *bufio.Reader, n int) []int {
	res := make([]int, n)
	x := 0
	bs, _ := reader.ReadBytes('\n')
	for i := 0; i < n; i++ {
		for x < len(bs) && (bs[x] < '0' || bs[x] > '9') {
			x++
		}
		x = readInt(bs, x, &res[i])
	}
	return res
}

func readUint64(bytes []byte, from int, val *uint64) int {
	i := from

	var tmp uint64
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + uint64(bytes[i]-'0')
		i++
	}
	*val = tmp

	return i
}

func fillNNums(bs []byte, n int, res []int) {
	x := 0
	for i := 0; i < n; i++ {
		for x < len(bs) && (bs[x] < '0' || bs[x] > '9') && bs[x] != '-' {
			x++
		}
		x = readInt(bs, x, &res[i])
	}
}

func main() {
	reader := bufio.NewReader(os.Stdin)

	n := readNum(reader)

	P := readNNums(reader, n)
	Q := readNNums(reader, n)

	res := solve(n, P, Q)

	for i := 0; i < n; i++ {
		fmt.Printf("%d ", res[i])
	}
}

func solve(n int, P []int, Q []int) []int {
	arr := make([]int, 4*n)
	add := make([]int, 4*n)

	update := func(p int, x int) {
		add[p] += x
		arr[p] += x
	}

	push := func(p int) {
		if add[p] != 0 {
			update(p*2+1, add[p])
			update(p*2+2, add[p])
			add[p] = 0
		}
	}

	var updateRange func(i int, l, r int, tl, tr int, x int)

	updateRange = func(i int, l, r int, tl, tr int, x int) {
		if tl >= r || tr <= l {
			return
		}
		if tl >= l && tr <= r {
			update(i, x)
			return
		}
		push(i)

		mid := (tl + tr) / 2

		updateRange(2*i+1, l, r, tl, mid, x)
		updateRange(2*i+2, l, r, mid, tr, x)

		arr[i] = min(arr[2*i+1], arr[2*i+2])
	}

	rev := make([]int, n+1)
	for i := 0; i < n; i++ {
		rev[P[i]] = i
	}

	decrease := func(x int) bool {
		updateRange(0, 0, rev[x]+1, 0, n, -1)
		if arr[0] >= 0 {
			return true
		}
		updateRange(0, 0, rev[x]+1, 0, n, 1)
		return false
	}

	ans := make([]int, n)
	x := n

	for i := 0; i < n; i++ {
		for decrease(x) {
			x--
		}
		ans[i] = x
		updateRange(0, 0, Q[i], 0, n, 1)
	}

	return ans
}

func min(a, b int) int {
	if a <= b {
		return a
	}
	return b
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

const N = 3000010
const INF = 1000000001
var n int
var a [N] int
var p [N] int
var pos[N] int

func max(a int, b int) int {
	if a < b {
		return b
	}
	return a
}

type SegNode struct {
	value int
	agg int
	max int
}

var Tree [4 * N] SegNode

func lazy(node int)  {
	if Tree[node].agg > 0 {
		Tree[node * 2].agg += Tree[node].agg
		Tree[node * 2 + 1].agg += Tree[node].agg
		Tree[node].agg = 0
	}
}

func addValue(node int, l int, r int, u int, v int, val int)  {
	if l > v || r < u {
		return
	}
	if l >= u && r <= v {
		Tree[node].agg += val
		return
	}

	var mid = (l + r) >> 1
	lazy(node)
	addValue(node * 2, l, mid, u, v, val)
	addValue(node * 2 + 1, mid + 1, r, u, v, val)
	Tree[node].max = max(Tree[node * 2].max + Tree[node * 2].agg, Tree[node * 2 + 1].max + Tree[node * 2 + 1].agg)
}

func getMax(node int, l int, r int, u int, v int) int {
	if r < u || l > v {
		return -INF
	}
	if l >= u && r <= v {
		return Tree[node].agg + Tree[node].max
	}
	var mid = (l + r) >> 1
	lazy(node)
	var maxValue = getMax(node * 2, l, mid, u, v)
	maxValue = max(maxValue, getMax(node * 2 + 1, mid + 1, r, u, v))
	return maxValue
}

func main()  {
	var reader = bufio.NewReader(os.Stdin)
	var writer = bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	fmt.Fscanf(reader, "%d\n", &n)
	for i:=0; i < n; i++ {
		fmt.Fscanf(reader,"%d", &a[i])
		pos[a[i]] = i + 1
	}
	fmt.Fscanf(reader,"\n")

	for i:=0; i < n; i++ {
		fmt.Fscanf(reader, "%d", &p[i])
	}

	var curAns = n
	addValue(1, 1, n, 1, pos[curAns], 1)

	for i := 0; i < n; i++ {

		for true {
			var maxValue = getMax(1, 1, n, 1, n)
			if maxValue > 0 {
				break
			}
			curAns--
			addValue(1, 1, n, 1, pos[curAns],1)
		}

		fmt.Fprintf(writer, "%d ", curAns)
		addValue(1, 1, n, 1, p[i], -1)

	}
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

const N = 3000010
const INF = 1000000001
var n int
var a [N] int
var p [N] int
var pos[N] int

func max(a int, b int) int {
	if a < b {
		return b
	}
	return a
}

type SegNode struct {
	value int
	agg int
	max int
}

var Tree [4 * N] SegNode

func lazy(node int)  {
	if Tree[node].agg > 0 {
		Tree[node * 2].agg += Tree[node].agg
		Tree[node * 2 + 1].agg += Tree[node].agg
		Tree[node].agg = 0
	}
}

func addValue(node int, l int, r int, u int, v int, val int)  {
	if l > v || r < u {
		return
	}
	if l >= u && r <= v {
		Tree[node].agg += val
		return
	}

	var mid = (l + r) >> 1
	lazy(node)
	addValue(node * 2, l, mid, u, v, val)
	addValue(node * 2 + 1, mid + 1, r, u, v, val)
	Tree[node].max = max(Tree[node * 2].max + Tree[node * 2].agg, Tree[node * 2 + 1].max + Tree[node * 2 + 1].agg)
}

func getMax(node int, l int, r int, u int, v int) int {
	if r < u || l > v {
		return -INF
	}
	if l >= u && r <= v {
		return Tree[node].agg + Tree[node].max
	}
	var mid = (l + r) >> 1
	lazy(node)
	var maxValue = getMax(node * 2, l, mid, u, v)
	maxValue = max(maxValue, getMax(node * 2 + 1, mid + 1, r, u, v))
	return maxValue
}

func main()  {
	var reader = bufio.NewReader(os.Stdin)
	var writer = bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	fmt.Fscanf(reader, "%d\n", &n)
	for i:=0; i < n; i++ {
		fmt.Fscanf(reader,"%d ", &a[i])
		pos[a[i]] = i + 1
	}

	for i:=0; i < n; i++ {
		fmt.Fscanf(reader, "%d ", &p[i])
	}

	var curAns = n
	addValue(1, 1, n, 1, pos[curAns], 1)

	for i := 0; i < n; i++ {

		for true {
			var maxValue = getMax(1, 1, n, 1, n)
			if maxValue > 0 {
				break
			}
			curAns--
			addValue(1, 1, n, 1, pos[curAns],1)
		}

		fmt.Fprintf(writer, "%d ", curAns)
		addValue(1, 1, n, 1, p[i], -1)

	}
}


This version of the problem differs from the previous one only in the constraint on $$$n$$$.A tree is a connected undirected graph without cycles. A weighted tree has a weight assigned to each edge. The distance between two vertices is the minimum sum of weights on the path connecting them.You are given a weighted tree with $$$n$$$ vertices, each edge has a weight of $$$1$$$. Denote $$$d(v)$$$ as the distance between vertex $$$1$$$ and vertex $$$v$$$.Let $$$f(x)$$$ be the minimum possible value of $$$\max\limits_{1 \leq v \leq n} \ {d(v)}$$$ if you can temporarily add an edge with weight $$$x$$$ between any two vertices $$$a$$$ and $$$b$$$ $$$(1 \le a, b \le n)$$$. Note that after this operation, the graph is no longer a tree.For each integer $$$x$$$ from $$$1$$$ to $$$n$$$, find $$$f(x)$$$.

The first line contains a single integer $$$t$$$ ($$$1 \le t \le 10^4$$$) — the number of test cases. The first line of each test case contains a single integer $$$n$$$ ($$$2 \le n \le 3 \cdot 10^5$$$). Each of the next $$$n−1$$$ lines contains two integers $$$u$$$ and $$$v$$$ ($$$1 \le u,v \le n$$$) indicating that there is an edge between vertices $$$u$$$ and $$$v$$$. It is guaranteed that the given edges form a tree. It is guaranteed that the sum of $$$n$$$ over all test cases doesn't exceed $$$3 \cdot 10^5$$$.

For each test case, print $$$n$$$ integers in a single line, $$$x$$$-th of which is equal to $$$f(x)$$$ for all $$$x$$$ from $$$1$$$ to $$$n$$$.

package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	in  = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
)

func flush()                            { out.Flush() }
func scan(a ...interface{})             { fmt.Fscan(in, a...) }
func printf(f string, a ...interface{}) { fmt.Fprintf(out, f, a...) }
func assert(f bool) {
	if !f {
		panic("gg")
	}
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// ----------------------------- TEMPLATE END ----------------------------------

const N = int(3e5 + 10)
const LOGN = int(19)

var ans []int
var graph [][]int
var sons [][]int
var depth []int
var maxDepth []int
var subTreeDiam []int

var preOrder []int
var preOrderInv []int
var subTreeSize []int
var firstAtDepth []int
var lastAtDepth []int

var ancestor [N][LOGN]int

func buildAncestors(n int) {
	// assuming ancestor[i][0] is the parent of i, for i in [0,n)
	for j := 0; j+1 < LOGN; j++ {
		for i := 0; i < n; i++ {
			ancestor[i][j+1] = ancestor[ancestor[i][j]][j]
		}
	}
}

func lca(a, b int) int {
	if depth[a] < depth[b] {
		a, b = b, a
	}
	var depthDiff = depth[a] - depth[b]
	for j := LOGN - 1; j >= 0; j-- {
		if ((depthDiff >> j) & 1) > 0 {
			a = ancestor[a][j]
		}
	}
	if a == b {
		return a
	}
	for j := LOGN - 1; j >= 0; j-- {
		if ancestor[a][j] != ancestor[b][j] {
			a = ancestor[a][j]
			b = ancestor[b][j]
		}
	}
	return ancestor[a][0]
}

func rootTree(i, pi int) {
	preOrderInv[i] = len(preOrder)
	preOrder = append(preOrder, i)
	ancestor[i][0] = pi
	if firstAtDepth[depth[i]] == -1 {
		firstAtDepth[depth[i]] = i
	}
	lastAtDepth[depth[i]] = i

	for _, j := range graph[i] {
		if j != pi {
			depth[j] = depth[i] + 1
			sons[i] = append(sons[i], j)
			rootTree(j, i)
		}
	}

	diam := 0
	var longestPaths [2]int = [2]int{depth[i], depth[i]}
	maxDepth[i] = depth[i]
	subTreeSize[i] = 1
	for _, j := range sons[i] {
		if maxDepth[j] > longestPaths[0] {
			longestPaths[1] = longestPaths[0]
			longestPaths[0] = maxDepth[j]
		} else if maxDepth[j] > longestPaths[1] {
			longestPaths[1] = maxDepth[j]
		}
		maxDepth[i] = max(maxDepth[i], maxDepth[j])
		subTreeSize[i] += subTreeSize[j]
		diam = max(subTreeDiam[j], diam)
	}

	diam = max(diam, longestPaths[0]+longestPaths[1]-2*depth[i])
	subTreeDiam[i] = diam
}

func solveCase() {
	var n int
	scan(&n)
	ans = make([]int, n+1)
	graph = make([][]int, n)
	sons = make([][]int, n)
	depth = make([]int, n)
	maxDepth = make([]int, n)
	subTreeDiam = make([]int, n)

	preOrderInv = make([]int, n)
	subTreeSize = make([]int, n)

	firstAtDepth = make([]int, n)
	lastAtDepth = make([]int, n)

	for i := 0; i < n; i++ {
		firstAtDepth[i] = -1
	}

	var a, b int
	for edges := 0; edges < n-1; edges++ {
		scan(&a, &b)
		a--
		b--
		graph[a] = append(graph[a], b)
		graph[b] = append(graph[b], a)
	}

	rootTree(0, 0)
	buildAncestors(n)

	for i := n - 1; i > 0; i-- {
		if firstAtDepth[i] == -1 {
			continue
		}
		if firstAtDepth[i-1] == -1 {
			firstAtDepth[i-1] = firstAtDepth[i]
			lastAtDepth[i-1] = lastAtDepth[i]
		} else {
			if preOrderInv[firstAtDepth[i]] < preOrderInv[firstAtDepth[i-1]] {
				firstAtDepth[i-1] = firstAtDepth[i]
			}
			if preOrderInv[lastAtDepth[i]] > preOrderInv[lastAtDepth[i-1]] {
				lastAtDepth[i-1] = lastAtDepth[i]
			}
		}
	}
	// printf("after:\n")
	// for i := 0; i < n; i++ {
	// 	printf("depth %d: %d, %d\n", i, firstAtDepth[i]+1, lastAtDepth[i]+1)
	// }

	// For every k, find the minimum x that can get me answer=k
	for i := 1; i <= n; i++ {
		ans[i] = maxDepth[0]
	}
	for k := 1; k <= n; k++ {
		var x int
		if k+1 >= n || firstAtDepth[k+1] == -1 {
			x = 0
		} else {
			node := lca(firstAtDepth[k+1], lastAtDepth[k+1])
			// printf("nodes = %d -> [%d,%d]. diam=%d\n", node+1, firstAtDepth[k+1]+1, lastAtDepth[k+1]+1, subTreeDiam[node])
			x = k - (subTreeDiam[node]+1)/2
		}
		if x >= 1 {
			ans[x] = min(k, ans[x])
		}
		// printf("minimum to get ans=%d is %d\n", k, x)
	}

	for i := n - 1; i >= 1; i-- {
		ans[i] = min(ans[i], ans[i+1])
	}

	for i := 1; i <= n; i++ {
		if i > 1 {
			printf(" ")
		}
		printf("%d", ans[i])
	}
	printf("\n")
}

func main() {
	defer flush()

	var ntc int
	scan(&ntc)
	for t := 0; t < ntc; t++ {
		solveCase()
	}
}


The only difference between the easy and hard versions is that the given string $$$s$$$ in the easy version is initially a palindrome, this condition is not always true for the hard version.A palindrome is a string that reads the same left to right and right to left. For example, "101101" is a palindrome, while "0101" is not.Alice and Bob are playing a game on a string $$$s$$$ of length $$$n$$$ consisting of the characters '0' and '1'. Both players take alternate turns with Alice going first.In each turn, the player can perform one of the following operations:   Choose any $$$i$$$ ($$$1 \le i \le n$$$), where $$$s[i] =$$$ '0' and change $$$s[i]$$$ to '1'. Pay 1 dollar.  Reverse the whole string, pay 0 dollars. This operation is only allowed if the string is currently not a palindrome, and the last operation was not reverse. That is, if Alice reverses the string, then Bob can't reverse in the next move, and vice versa. Reversing a string means reordering its letters from the last to the first. For example, "01001" becomes "10010" after reversing.The game ends when every character of string becomes '1'. The player who spends minimum dollars till this point wins the game and it is a draw if both spend equal dollars. If both players play optimally, output whether Alice wins, Bob wins, or if it is a draw.

The first line contains a single integer $$$t$$$ ($$$1 \le t \le 10^3$$$). Then $$$t$$$ test cases follow. The first line of each test case contains a single integer $$$n$$$ ($$$1 \le n \le 10^3$$$). The second line of each test case contains the string $$$s$$$ of length $$$n$$$, consisting of the characters '0' and '1'. It is guaranteed that the string $$$s$$$ contains at least one '0'. Note that there is no limit on the sum of $$$n$$$ over test cases.

For each test case print a single word in a new line:    "ALICE", if Alice will win the game,  "BOB", if Bob will win the game,  "DRAW", if the game ends in a draw.

NoteIn the first test case of example,   in the $$$1$$$-st move, Alice will use the $$$2$$$-nd operation to reverse the string, since doing the $$$1$$$-st operation will result in her loss anyway. This also forces Bob to use the $$$1$$$-st operation.  in the $$$2$$$-nd move, Bob has to perform the $$$1$$$-st operation, since the $$$2$$$-nd operation cannot be performed twice in a row. All characters of the string are '1', game over.  Alice spends $$$0$$$ dollars while Bob spends $$$1$$$ dollar. Hence, Alice wins.In the second test case of example,   in the $$$1$$$-st move Alice has to perform the $$$1$$$-st operation, since the string is currently a palindrome.  in the $$$2$$$-nd move Bob reverses the string.  in the $$$3$$$-rd move Alice again has to perform the $$$1$$$-st operation. All characters of the string are '1', game over.  Alice spends $$$2$$$ dollars while Bob spends $$$0$$$ dollars. Hence, Bob wins.

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				fmt.Println("ALICE")
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					fmt.Println("ALICE")
				} else {
					if ZeroISThere == 2 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("ALICE")
					}
				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				fmt.Println("ALICE")
			} else {
				fmt.Println("ALICE")

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	reader = bufio.NewReader(os.Stdin)
	writer = bufio.NewWriter(os.Stdout)
)

func scan(a ...interface{})             { fmt.Fscan(reader, a...) }
func printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }

func redirectInputToFile(r *bufio.Reader, fp string) {
	f, err := os.Open(fp)
	if err != nil {
		panic(err)
	}
	r.Reset(f)
}

func main() {
	defer writer.Flush()
	// redirectInputToFile(reader, "input.txt")

	T := 1
	scan(&T)
	for t := 0; t < T; t++ {
		solve()
	}
}

func solve() {
	var n int
	scan(&n)
	var s string
	scan(&s)
	var c0, c01, c00 int
	if n%2 == 1 && s[n/2] == '0' {
		c0++
	}
	for i := 0; i < n/2; i++ {
		if s[i] != s[n-1-i] {
			c01++
		} else if s[i] == '0' {
			c00++
		}
	}
	if c01 > 1 {
		printf("ALICE\n")
		return
	}
	if c00 == 0 {
		if c01 == 1 && c0 == 1 {
			printf("DRAW\n")
		}
		if c01 == 1 && c0 == 0 {
			printf("ALICE\n")
		}
		if c01 == 0 && c0 == 1 {
			printf("BOB\n")
		}
		return
	}
	if c0 == 0 && c01 == 1 {
		printf("ALICE\n")
		return
	}
	if c0 == 0 && c01 == 0 {
		printf("BOB\n")
		return
	}
	if c0 == 1 && c01 == 0 {
		printf("ALICE\n")
		return
	}
	if c0 == 1 && c01 == 1 {
		printf("ALICE\n")
		return
	}
}

package main

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

func main() {
	in := bufio.NewReader(Stdin)
	var T, n int
	var s string
	for Fscan(in, &T); T > 0; T-- {
		Fscan(in, &n, &s)
		isP := true
		for i := 0; i < n/2; i++ {
			if s[i] != s[n-1-i] {
				isP = false
				break
			}
		}
		c := Count(s, "0")
		if isP {
			if c&1 > 0 && c > 1 {
				Println("ALICE")
			} else {
				Println("BOB")
			}
		} else if n&1 > 0 && s[n/2] == '0' && c == 2 {
			Println("DRAW")
		} else {
			Println("ALICE")
		}
	}
}

package main
import("bufio";."fmt";."os";."strings")

// github.com/EndlessCheng/codeforces-go
func main(){
	in:=bufio.NewReader(Stdin)
	T,n,s:=0,0,""
	for Fscan(in,&T);T>0;T--{
		Fscan(in,&n,&s)
		d:=0
		for i:=0;i<n/2;i++{if s[i]!=s[n-1-i]{d++}}
		if c:=Count(s,"0");d==0{
			if c&1>0&&c>1{Println("ALICE")
			}else{Println("BOB")}
		}else if n&1>0&&s[n/2]=='0'&&c==2{Println("DRAW")
		}else{Println("ALICE")}
	}
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
)

// github.com/EndlessCheng/codeforces-go
func run(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	solve := func(Case int) {
		var n, diff int
		var s string
		Fscan(in, &n, &s)
		for i, j := 0, n-1; i < j; i++ {
			if s[i] != s[j] {
				diff++
			}
			j--
		}
		c0 := strings.Count(s, "0")

		if diff == 0 {
			if c0&1 == 0 {
				Fprintln(out, "BOB")
			} else {
				if c0 == 1 {
					Fprintln(out, "BOB")
				} else {
					Fprintln(out, "ALICE")
				}
			}
			return
		}

		if n&1 == 0 || s[n/2] == '1' {
			Fprintln(out, "ALICE")
		} else {
			if diff == 1 {
				if c0 == 2 {
					Fprintln(out, "DRAW")
				} else {
					Fprintln(out, "ALICE")
				}
			} else {
				Fprintln(out, "ALICE")
			}
		}
	}

	T := 1
	Fscan(in, &T) //
	for Case := 1; Case <= T; Case++ {
		solve(Case)
	}

	_leftData, _ := ioutil.ReadAll(in)
	if _s := strings.TrimSpace(string(_leftData)); _s != "" {
		panic("有未读入的数据：\n" + _s)
	}
}

func main() { run(os.Stdin, os.Stdout) }

package main
import("bufio";."fmt";."os";."strings")

func main() {
	in := bufio.NewReader(Stdin)
	var T, n int
	var s string
	for Fscan(in, &T); T > 0; T-- {
		Fscan(in, &n, &s)
		isP := true
		for i := 0; i < n/2; i++ {
			if s[i] != s[n-1-i] {
				isP = false
				break
			}
		}
		c := Count(s, "0")
		if isP {
			if c&1 > 0 && c > 1 {
				Println("ALICE")
			} else {
				Println("BOB")
			}
		} else if n&1 > 0 && s[n/2] == '0' && c == 2 {
			Println("DRAW")
		} else {
			Println("ALICE")
		}
	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				if ZeroISThere == 1 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("BOb")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 1 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("BoB")
					}
				} else {
					if ZeroISThere == 2 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("ALICE")
					}
				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				if ZeroISThere == 2 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("DRAW")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 2 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("DRAW")
					}
				} else {
					fmt.Println("ALICE")
				}

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				if ZeroISThere == 1 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 1 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("BoB")
					}
				} else {
					if ZeroISThere == 2 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("ALICE")
					}
				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				if ZeroISThere == 2 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("DRAW")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 2 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("DRAW")
					}
				} else {
					fmt.Println("ALICE")
				}

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				if ZeroISThere == 1 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 1 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 2 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("ALICE")
					}
				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				if ZeroISThere == 2 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("DRAW")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 2 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("DRAW")
					}
				} else {
					fmt.Println("ALICE")
				}

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				if ZeroISThere == 1 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("ALICE")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 1 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("BOB")
					}
				} else {

					fmt.Println("ALICE")

				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				if ZeroISThere == 2 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("ALICE")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 2 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("DRAW")
					}
				} else {
					if ZeroISThere == 3 {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				if ZeroISThere == 1 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("ALICE")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 1 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("BOB")
					}
				} else {

					fmt.Println("ALICE")

				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				if ZeroISThere == 2 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("ALICE")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 2 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("ALICE")
					}
				} else {
					if ZeroISThere == 3 {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				if ZeroISThere == 1 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("ALICE")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 1 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("BOB")
					}
				} else {

					fmt.Println("ALICE")

				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				if ZeroISThere == 2 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("DRAW")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 2 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("DRAW")
					}
				} else {
					if ZeroISThere == 3 {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				if ZeroISThere == 1 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 1 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("ALICE")
					}
				} else {

					fmt.Println("ALICE")

				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				if ZeroISThere == 2 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("DRAW")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 2 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("DRAW")
					}
				} else {
					if ZeroISThere == 3 {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
)

// var m []int
// err = json.Unmarshal([]byte(r.FormValue("example")), &m)

// for i := 0; i < len(m); i++ {
// 	fmt.Println(m[i])
// }

// sort.Slice(arr, func(i, j int) bool {
// 	return arr[i] > arr[j]
// })

func MIN(x, y int64) int64 {
	if x > y {
		return y
	} else {
		return x
	}
}

func MKO(x, y int64) int64 {
	if x < y {
		return 0
	} else {
		return x - y + 1
	}
}

func MAX(x, y int64) int64 {
	if x > y {
		return x
	} else {
		return y
	}
}

func LCM(x, y int) int {
	if x >= y {
		initial := x
		for i := 1; i < y+2; i++ {
			if initial%y == 0 {
				break
			} else {
				initial = initial + x
			}

		}
		return initial
	} else {
		initial := y
		for i := 1; i < x+2; i++ {
			if initial%x == 0 {
				break
			} else {
				initial = initial + y
			}

		}
		return initial
	}
}

func GCD(x, y int64) int64 {
	var l, q int64
	l = MAX(x, y)
	q = MIN(x, y)
	var m int64
	for l*q > 0 {
		a := l % q
		b := l - a
		cc := int64(b / q)
		remain := l - cc*q
		l = MAX(remain, q)
		q = MIN(remain, q)
		if l*q == 0 {
			m = l + q
			break
		}

	}
	return m

}

func IsItPrime(x int) bool {
	if x < 10 {
		if x == 2 || x == 3 || x == 5 || x == 7 {
			return true
		} else {
			return false
		}
	} else {
		j := 0
		k := math.Sqrt(float64(x))
		for m := 3; m <= int(k); {
			if x%m == 0 {
				j = 1
				break
			}
			m = m + 2
		}
		if j == 1 {
			return false
		} else {
			return true
		}
	}

}

var t int

func main() {
	var input io.Reader = bufio.NewReader(os.Stdin)
	fmt.Fscan(input, &t)

	for o := 0; o < t; o++ {
		var n int
		fmt.Fscan(input, &n)
		STRING := make([]byte, 0)
		fmt.Fscan(input, &STRING)
		k := int(n / 2)
		notequal := 0
		for i := 0; i < k; i++ {
			if string(STRING[i]) != string(STRING[n-1-i]) {
				notequal++
			}
		}
		ZeroISThere := 0
		for i := 0; i < n; i++ {
			if string(STRING[i]) == "0" {
				ZeroISThere++
			}
		}
		if notequal == 0 {
			if n%2 == 0 {
				if ZeroISThere == 0 {
					fmt.Println("DRAW")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 0 {
						fmt.Println("DRAW")
					} else {
						fmt.Println("BOB")
					}
				} else {
					if ZeroISThere == 1 {
						fmt.Println("BOB")
					} else {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal == 1 {
			if n%2 == 0 {
				if ZeroISThere == 1 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("BOB")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 1 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("BOB")
					}
				} else {

					fmt.Println("ALICE")

				}

			}
		}
		if notequal == 2 {
			if n%2 == 0 {
				if ZeroISThere == 2 {
					fmt.Println("ALICE")
				} else {
					fmt.Println("DRAW")
				}
			} else {
				q := int((n - 1) / 2)
				if string(STRING[q]) == "1" {
					if ZeroISThere == 2 {
						fmt.Println("ALICE")
					} else {
						fmt.Println("DRAW")
					}
				} else {
					if ZeroISThere == 3 {
						fmt.Println("ALICE")

					}
				}

			}
		}
		if notequal > 2 {
			fmt.Println("ALICE")
		}

	}
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	reader = bufio.NewReader(os.Stdin)
	writer = bufio.NewWriter(os.Stdout)
)

func scan(a ...interface{})             { fmt.Fscan(reader, a...) }
func printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }

func redirectInputToFile(r *bufio.Reader, fp string) {
	f, err := os.Open(fp)
	if err != nil {
		panic(err)
	}
	r.Reset(f)
}

func main() {
	defer writer.Flush()
	// redirectInputToFile(reader, "input.txt")

	T := 1
	scan(&T)
	for t := 0; t < T; t++ {
		solve()
	}
}

func solve() {
	var n int
	scan(&n)
	var s string
	scan(&s)
	var c0, c01, c00 int
	if n%2 == 1 && s[n/2] == '0' {
		c0++
	}
	for i := 0; i < n/2; i++ {
		if s[i] != s[n-1-i] {
			c01++
		} else if s[i] == '0' {
			c00++
		}
	}
	if c01 > 1 {
		printf("ALICE\n")
		return
	}
	if c00 == 0 {
		if c01 == 1 && c0 == 1 {
			printf("DRAW\n")
		}
		if c01 == 1 && c0 == 0 {
			printf("ALICE\n")
		}
		if c01 == 0 && c0 == 1 {
			printf("BOB\n")
		}
		return
	}
	if c0 == 0 && c01 == 1 {
		printf("ALICE\n")
		return
	}
	if c0 == 0 && c01 == 0 {
		printf("BOB\n")
		return
	}
	if c0 == 1 && c01 == 0 {
		printf("ALICE\n")
		return
	}
	if c0 == 1 && c01 == 1 {
		printf("BOB\n")
		return
	}
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	reader = bufio.NewReader(os.Stdin)
	writer = bufio.NewWriter(os.Stdout)
)

func scan(a ...interface{})             { fmt.Fscan(reader, a...) }
func printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }

func redirectInputToFile(r *bufio.Reader, fp string) {
	f, err := os.Open(fp)
	if err != nil {
		panic(err)
	}
	r.Reset(f)
}

func main() {
	defer writer.Flush()
// 	redirectInputToFile(reader, "input.txt")

	precompute()
	T := 1
	scan(&T)
	for t := 0; t < T; t++ {
		solve()
	}
}

const inf = 1 << 30

var dp [1001][1001][2][2]int

func min(s []int) int {
	r := s[0]
	for _, i := range s {
		if r > i {
			r = i
		}
	}
	return r
}

func calcdp(c01, c00, c0, canrev, player int) {
	if dp[c01][c00][c0][canrev] != inf {
		return
	}
	res := []int{}
	if canrev == 1 && c01 > 0 {
		calcdp(c01, c00, c0, 0, player^1)
		res = append(res, -dp[c01][c00][c0][0])
	}
	if c01 > 0 {
		calcdp(c01-1, c00, c0, 1, player^1)
		res = append(res, -dp[c01-1][c00][c0][1]+1)
	}
	if c00 > 0 {
		calcdp(c01, c00-1, c0, 1, player^1)
		res = append(res, -dp[c01][c00-1][c0][1]+1)
	}
	if c0 > 0 {
		calcdp(c01, c00, c0-1, 1, player^1)
		res = append(res, -dp[c01][c00][c0-1][1]+1)
	}
	dp[c01][c00][c0][canrev] = min(res)
}

func precompute() {
	for i := range dp {
		for j := range dp[i] {
			for k := range dp[i][j] {
				for l := range dp[i][j][k] {
					dp[i][j][k][l] = inf
				}
			}
		}
	}
	dp[0][0][0][0] = 0
	dp[0][0][0][1] = 0
	for i := range dp {
		for j := range dp[i] {
			for k := range dp[i][j] {
				calcdp(i, j, k, 1, 0)
			}
		}
	}
}

func solve() {
	var n int
	scan(&n)
	var s string
	scan(&s)
	var c0, c01, c00 int
	if n%2 == 1 && s[n/2] == '0' {
		c0++
	}
	for i := 0; i < n/2; i++ {
		if s[i] != s[n-1-i] {
			c01++
		} else if s[i] == '0' {
			c00++
		}
	}
	var ans = "DRAW"
	if dp[c01][c00][c0][1] > 0 {
		ans = "BOB"
	}
	if dp[c01][c00][c0][1] < 0 {
		ans = "ALICE"
	}
	printf("%v\n", ans)
}