import std.algorithm, std.container, std.conv, std.math, std.range, std.typecons, std.stdio, std.string;

auto rdsp(){return readln.splitter;}
void pick(R,T)(ref R r,ref T t){t=r.front.to!T;r.popFront;}
void readV(T...)(ref T t){auto r=rdsp;foreach(ref v;t)pick(r,v);}
void readA(T)(size_t n,ref T[]t){t=new T[](n);auto r=rdsp;foreach(ref v;t)pick(r,v);}

void main()
{
  int n; readV(n);
  dchar[][] s; readA(n, s);

  foreach (i; 0..n)
    s[i] = s[i].sort().uniq.array;

  s = s.sort().uniq.array;

  writeln(s.length);
}

import std.stdio;
import std.range;
import std.array;
import std.string;
import std.conv;
import std.typecons;
import std.algorithm;
import std.container;
import std.typecons;
import std.random;
import std.csv;
import std.regex;
import std.math;
import core.time;
import std.ascii;
import std.digest.sha;
import std.outbuffer;

void main()
{
	int n = readln.chomp.to!int;
	string[] ss = readln.chomp.split;
	bool[bool[char]] roots;
	foreach (s; ss) {
		bool[char] root;
		foreach (c; s) {
			root[c] = true;
		}
		roots[root] = true;
	}
	roots.length.writeln;
}

void tie(R, Args...)(R arr, ref Args args)
		if (isRandomAccessRange!R || isArray!R)
in
{
	assert (arr.length == args.length);
}
body
{
	foreach (i, ref v; args) {
		alias T = typeof(v);
		v = arr[i].to!T;
	}
}

void verbose(Args...)(in ref Args args)
{
	stderr.write("[");
	foreach (i, ref v; args) {
		if (i) stderr.write(", ");
		stderr.write(v);
	}
	stderr.writeln("]");
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.splitter.map!(to!(dchar[])).array;

    auto toRoot = (dchar[] s) => s.sort.uniq.to!(dchar[]);

    auto ans = a.map!toRoot.redBlackTree.length;

    writeln (ans);
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.splitter.map!(to!(dchar[])).array;

    auto toRoot = (dchar[] s) => s.sort.uniq.to!(dchar[]);

    auto ans = a.map!(toRoot).redBlackTree.length;

    writeln (ans);
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.split.map!(to!string).array;

    auto rbt = make!(RedBlackTree!string);

    auto toRoot = (string s) => s.representation.dup.sort.uniq.to!string;

    a.each!(s => rbt.insert(toRoot(s)));

    debug { writeln(rbt); }

    writeln (rbt.length);
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.split.map!(to!(dchar[])).array;

    auto rbt = make!(RedBlackTree!(dchar[]));

    auto toRoot = (dchar[] s) => s.sort.uniq.to!(dchar[]);

    a.each!(s => rbt.insert(toRoot(s)));

    debug { writeln(rbt); }

    writeln (rbt.length);
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.splitter.map!(to!(dchar[]));

    auto toRoot = (dchar[] s) => s.sort.uniq.array;

    auto ans = a.map!toRoot.redBlackTree.length;

    writeln (ans);
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.split.map!(to!(dchar[])).array;

    auto toRoot = (dchar[] s) => s.sort.uniq.to!(dchar[]);

    auto ans = a.map!(toRoot).redBlackTree.length;

    writeln (ans);
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.splitter;

    auto toRoot = (string s) => s.array.sort.uniq.to!string;

    auto ans = a.map!toRoot.redBlackTree.length;

    writeln (ans);
}

import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.splitter.map!(to!(dchar[]));

    auto toRoot = (dchar[] s) => s.sort.uniq.to!(dchar[]);

    auto ans = a.map!toRoot.redBlackTree.length;

    writeln (ans);
}


//ahmat
import core.stdc.stdio:scanf,printf,puts;
import core.bitop;
import std.stdio;
import std.string;
import std.algorithm;
import std.functional;
import std.array;
import std.container;
import std.conv;
import std.container;
import std.typecons;
import std.math;
import std.numeric;
pragma(inline,true);

void main(){
    double a,b,n,x,y,v,ans=double.max;
    readf!"%f %f"(a,b);
    readln;
    n=readln.chomp.to!int;
    while(n--){
        readf!"%f %f %f"(x,y,v);
        readln;
        ans=min(ans,sqrt((a-x)^^2+(b-y)^^2)/v);
    }
    writefln!"%.10f"(ans);
}

//ahmat
import core.stdc.stdio:scanf,printf,puts;
import core.bitop;
import std.stdio;
import std.string;
import std.algorithm;
import std.functional;
import std.array;
import std.container;
import std.conv;
import std.container;
import std.typecons;
import std.math;
import std.numeric;
pragma(inline,true);

void main(){
    double a,b,x,y,v,ans=double.max;
    readf!"%f %f"(a,b);
    readln;
    int n=readln.chomp.to!int;
    while(n--){
        readf!"%f %f %f"(x,y,v);
        readln;
        ans=min(ans,sqrt((a-x)^^2+(b-y)^^2)/v);
    }
    writefln!"%.10f"(ans);
}


import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.typecons;

void main ()
{
	int n, m;
	while (readf (" %s %s", &n, &m) > 0)
	{
		alias Segment = Tuple !(int, q{l}, int, q{r});
		auto s = new Segment [n];
		foreach (ref c; s)
		{
			readf (" %s %s", &c.l, &c.r);
		}
		auto r = iota (1, m + 1)
		    .filter !(x => s.all !(c => x < c.l || c.r < x)).array;
		writeln (r.length);
		writefln ("%(%s %)", r);
	}
}

import std.stdio;
int main()
{
	int a=0;
	int b=0;
	readf(" %d", &a);
	readf(" %d", &b);
	bool[] m = new bool[b+1];
	for (int i=0; i<b+1; i++)
	{
		m[i]=true;
	}
	for (int i=0; i<a; i++)
	{
		int c=0;
		int d=0;
		readf(" %d", &c);
		readf(" %d", &d);
		for (int j=c; j<d+1; j++)
		{
			m[j]=false;
		}
	}
	int count=0;
	for (int i=0; i<b+1; i++)
	{
		if (m[i]==true)
		{
			count=count+1;
		}
	}
	writeln(count-1);
	for (int i=1; i<b+1; i++)
	{
		if (m[i]==true)
		{
			writeln(i);
		}
	}
	return 0;
}

import core.bitop;
import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import std.range.interfaces;

void main()
{
    int n, m;
    readf("%s %s", &n, &m);
    readln;

    auto cnt = new int[] (m+2);
    foreach (_; 0 .. n) {
        int a, b;
        readf("%s %s", &a, &b);
        readln;

        ++cnt[a];
        --cnt[b+1];
    }

    cnt = cnt.cumulativeFold!((a, b) => a + b).array;

    auto ans = cnt.dropOne.dropBackOne.enumerate(1).filter!(t => t[1] == 0).map!(t => t[0]).array;

    ans.length.writeln;
    ans.writefln!("%(%s %)");
}


import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string rstring(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T rtype(T)(){ return rstring.to!T; } alias rint = rtype!int, rlong = rtype!long, rreal = rtype!real;
T[] rtypes(T)(int n){ return n.iota.map!(i => rtype!T()).array; } alias rint = rtypes!int, rlong = rtypes!long, rreal = rtypes!real;
T[][] rtypess(T)(int n, int m){ return n.iota.map!(i => rtypes!T(m)).array; } alias rint = rtypess!int, rlong = rtypess!long, rreal = rtypess!real;

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int n = rint;
	P[] ps;
	foreach(i; 0 .. n){
		ps ~= P(i, i + 1, rlong, rlong, rlong);
	}

	P[][long][long] pm;
	foreach(p; ps){
		if(p.x !in pm){
			P[][long] tmp;
			pm[p.x] = tmp;
		}
		if(p.y !in pm[p.x]) pm[p.x][p.y] = [];
		pm[p.x][p.y] ~= p;
	}

	int[][] ans;

	long[] xs = pm.keys;
	xs.sort();
	P superleft;
	bool hasSuperleft;
	foreach(x; xs){
		long[] ys = pm[x].keys;
		ys.sort();
		P left;
		bool hasLeft;
		foreach(y; ys){
			P[] pq = pm[x][y];
			pq.sort!isLess();
			foreach(i; 0 .. pq.length / 2){
				ans ~= [pq[i * 2].name, pq[i * 2 + 1].name];
			}
			if(pq.length % 2){
				if(hasLeft){
					ans ~= [pq[$ - 1].name, left.name];
					hasLeft = 0;
				}
				else{
					left = pq[$ - 1];
					hasLeft = 1;
				}
			}
		}
		if(hasLeft){
			if(hasSuperleft){
				ans ~= [left.name, superleft.name];
				hasLeft = 0, hasSuperleft = 0;
			}
			else{
				superleft = left;
				hasLeft = 0, hasSuperleft = 1;
			}
		}
	}

	foreach(an; ans) writeln(an[0], " ", an[1]);
}

struct P{
	int id, name;
	long x, y, z;
}
bool isLess(P a, P b){
	if(a.x != b.x) return a.x < b.x;
	if(a.y != b.y) return a.y < b.y;
	return a.z < b.z;
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static string[] s_rd;
T RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
string RDR()() { return readln.chomp; }
T[] ARR(T = long)(in string str, T fix = 0) { auto r = str.split.to!(T[]); r[] += fix; return r; }
T[] RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[][] RDA2(T = long)(size_t n, T[] fix = []) { auto r = new T[][](n); foreach (i; 0..n) { r[i] = readln.chomp.split.to!(T[]); foreach (j, e; fix) r[i][j] += e; } return r; }
size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
long lcm(long x, long y) { return x * (y / gcd(x, y)); }

long mod = 10^^9 + 7;
//long mod = 998_244_353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }

void main()
{
	auto n = RD!int;
	long[3][int] list;
	foreach (i; 0..n)
	{
		list[i] = [RD, RD, RD];
	}

	int[2][] ans;
	while (true)
	{
		auto keys = list.keys;
		if (keys.length == 0) break;
		auto k1 = keys[0];
		int pos;
		long best = long.max;
		foreach (k2; keys[1..$])
		{
			auto lhs = list[k1].dup;
			auto rhs = list[k2];
			lhs[] -= rhs[];
			lhs[] *= lhs[];
			long d;
			foreach (e; lhs)
				d += e;
			if (d < best)
			{
				pos = k2;
				best = d;
			}
		}
		ans ~= [k1, pos];
		list.remove(k1);
		list.remove(pos);
	}

	foreach (e; ans)
		writeln(e[0]+1, " ", e[1]+1);
	stdout.flush();
	debug readln();
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.ascii, std.typecons;

void main()
{
    auto n = readln.chomp.to!int;

    Tuple!(int, int)[][int][int] mp;
    foreach (int i; 1 .. n+1) {
        auto v = readln.chomp.split.map!(to!int);
        auto x = v[0], y = v[1], z = v[2];

        mp[x][y] ~= tuple(z, i);
    }

    debug { mp.writeln; }

    Tuple!(int, int)[] ans;

    void takePairs(ref int[] arr, ref int[] leftOvers) {
        while (arr.length > 1) {
            auto idx1 = arr.back;
            arr.popBack();
            auto idx2 = arr.back;
            arr.popBack();
            ans ~= tuple(idx1, idx2);
        }

        if (arr.length == 1) {
            leftOvers ~= arr.back;
            arr.popBack();
        }
    }

    int[] lftx;
    foreach (xx; mp.keys.sort()) {
        int[] lfty;
        foreach (yy; mp[xx].keys.sort()) {
            auto values = mp[xx][yy].sort().map!(t => t[1]).array;
            takePairs(values, lfty);
        }

        takePairs(lfty, lftx);
    }

    int[] dummy;
    takePairs(lftx, dummy);

    ans.each!(t => writeln(t[0], ' ', t[1]));
}

import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;

struct Point
{
	int x;
	int y;
	int z;
	int num;
}

long dist2 () (const auto ref Point p, const auto ref Point q)
{
	return (p.x - 0L - q.x) ^^ 2 + (p.y - 0L - q.y) ^^ 2 +
	    (p.z - 0L - q.z) ^^ 2;
}

void main ()
{
	int n;
	while (readf (" %s", &n) > 0)
	{
		auto p = new Point [n];
		foreach (i, ref q; p)
		{
			readf (" %s %s %s", &q.x, &q.y, &q.z);
			q.num = i + 1;
		}

		int [] [] res;
		while (!p.empty)
		{
			auto i = 0;
			auto j = 1;
			foreach (k; 2..p.length)
			{
				if (dist2 (p[i], p[j]) > dist2 (p[i], p[k]))
				{
					j = k;
				}
			}
			res ~= [p[i].num, p[j].num];
			p = p[1..j] ~ p[j + 1..$];
		}
		writefln ("%(%(%s %)\n%)", res);
	}
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.complex, std.container, std.math, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

alias Pt = Tuple!(int, "x", int, "y", int, "z", int, "id");

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      auto P = new Pt[N];
      foreach (i; 0 .. N) {
        P[i].x = readInt();
        P[i].y = readInt();
        P[i].z = readInt();
        P[i].id = i;
      }

      sort(P);

      int[] ans;

      int[] as;
      for (int i = 0, j; i < N; i = j) {
        for (j = i; j < N && P[i].x == P[j].x; ++j) {}
        int[] bs;
        for (int k = i, l; k < j; k = l) {
          for (l = k; l < j && P[k].y == P[l].y; ++l) {}
          foreach (m; k .. k + (l - k) / 2 * 2) {
            ans ~= P[m].id;
          }
          if ((l - k) % 2 != 0) {
            bs ~= P[l - 1].id;
          }
        }
        const bsLen = cast(int)(bs.length);
        foreach (m; 0 .. bsLen / 2 * 2) {
          ans ~= bs[m];
        }
        if (bsLen % 2 != 0) {
          as ~= bs[$ - 1];
        }
      }
      assert(as.length % 2 == 0);
      ans ~= as;

      for (int i = 0; i < N; i += 2) {
        writeln(ans[i] + 1, " ", ans[i + 1] + 1);
      }
    }
  } catch (EOFException e) {
  }
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.ascii, std.typecons;

void main()
{
    auto n = readln.chomp.to!int;

    Tuple!(int, int)[][int][int] mp;
    foreach (int i; 1 .. n+1) {
        auto v = readln.chomp.split.map!(to!int);
        auto x = v[0], y = v[1], z = v[2];

        mp[x][y] ~= tuple(z, i);
    }

    debug { mp.writeln; }

    Tuple!(int, int)[] ans;

    void takePairs(ref int[] arr, ref int[] leftOvers) {
        while (arr.length > 1) {
            auto idx1 = arr.back;
            arr.popBack();
            auto idx2 = arr.back;
            arr.popBack();
            ans ~= tuple(idx1, idx2);
        }

        if (arr.length == 1) {
            leftOvers ~= arr.back;
            arr.popBack();
        }
    }

    int[] lftx;
    foreach (xx; mp.keys) {
        int[] lfty;
        foreach (yy; mp[xx].keys) {
            auto values = mp[xx][yy].map!(t => t[1]).array;
            takePairs(values, lfty);
        }

        takePairs(lfty, lftx);
    }

    int[] dummy;
    takePairs(lftx, dummy);

    ans.each!(t => writeln(t[0], ' ', t[1]));
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional, std.meta;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.ascii, std.typecons;

void main()
{
    auto n = readln.chomp.to!int;

    Tuple!(int, int)[][int][int] mp;
    foreach (int i; 1 .. n+1) {
        auto v = readln.chomp.split.map!(to!int);
        auto x = v[0], y = v[1], z = v[2];

        mp[x][y] ~= tuple(z, i);
    }

    debug { mp.writeln; }

    Tuple!(int, int)[] ans;

    void takePairs(ref int[] arr, ref int[] leftOvers) {
        while (arr.length > 1) {
            auto idx1 = arr.back;
            arr.popBack();
            auto idx2 = arr.back;
            arr.popBack();
            ans ~= tuple(idx1, idx2);
        }

        if (arr.length == 1) {
            leftOvers ~= arr.back;
            arr.popBack();
        }
    }

    int[] lftx;
    foreach (xx; mp.keys) {
        int[] lfty;
        foreach (yy; mp[xx].keys) {
            auto values = mp[xx][yy]
                .schwartzSort!(t => t[0])
                .map!(t => t[1]).array;
            takePairs(values, lfty);
        }

        takePairs(lfty, lftx);
    }

    int[] dummy;
    takePairs(lftx, dummy);

    ans.each!(t => writeln(t[0], ' ', t[1]));
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.complex, std.container, std.math, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

alias Pt = Tuple!(int, "x", int, "y", int, "z", int, "id");

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      auto P = new Pt[N];
      foreach (i; 0 .. N) {
        P[i].x = readInt();
        P[i].y = readInt();
        P[i].z = readInt();
        P[i].id = i;
      }

      sort(P);
      for (int a = 0, i = 0, j; i < N; i = j) {
        for (j = i; j < N && P[i].x == P[j].x; ++j) {}
        if (a++ % 2 != 0) {
          reverse(P[i .. j]);
        }
        for (int b = 0, k = i, l; k < j; k = l) {
          for (l = k; l < j && P[k].y == P[l].y; ++l) {}
          if (b++ % 2 != 0) {
            reverse(P[k .. l]);
          }
        }
      }
      debug {
        writeln("P = ", P);
      }

      for (int i = 0; i < N; i += 2) {
        writeln(P[i].id + 1, " ", P[i + 1].id + 1);
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.complex, std.container, std.math, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

alias Pt = Tuple!(int, "x", int, "y", int, "z", int, "id");

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      auto P = new Pt[N];
      foreach (i; 0 .. N) {
        P[i].x = readInt();
        P[i].y = readInt();
        P[i].z = readInt();
        P[i].id = i;
      }

      sort(P);
      for (int a = 0, i = 0, j; i < N; i = j) {
        for (j = i; j < N && P[i].x == P[j].x; ++j) {}
        for (int b = 0, k = i, l; k < j; k = l) {
          for (l = k; l < j && P[k].y == P[l].y; ++l) {}
          if (b++ % 2 != 0) {
            reverse(P[k .. l]);
          }
        }
        if (a++ % 2 != 0) {
          reverse(P[i .. j]);
        }
      }
      debug {
        writeln("P = ", P);
      }

      for (int i = 0; i < N; i += 2) {
        writeln(P[i].id + 1, " ", P[i + 1].id + 1);
      }
    }
  } catch (EOFException e) {
  }
}


import std.stdio, std.string, std.conv, std.algorithm, std.numeric;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

immutable inf = 10^^9 + 7;

void main() {
    int n, d;
    scan(n, d);
    auto a = readln.split.to!(int[]);

    auto rw = new long[](n + 1);
    foreach (i ; 1 .. n + 1) {
        rw[i] = rw[i-1] + a[i-1];
    }

    auto rm = new long[](n + 1);
    rm[n] = rw[n];

    foreach_reverse (i ; 1 .. n) {
        rm[i] = max(rm[i + 1], rw[i]);
    }

    debug {
        writeln(rm);
    }

    int ans;
    long bank;

    foreach (i ; 0 .. n) {
        if (a[i] == 0 && bank < 0) {
            ans++;
            bank = d - (rm[i] - rw[i]);

            if (bank < 0) {
                writeln(-1);
                return;
            }
        }

        bank += a[i];

        debug {
            writeln(bank);
        }

        if (bank > d) {
            writeln(-1);
            return;
        }
    }

    writeln(ans);
}

struct UnionFind {
    private {
        int N;
        int[] p;
        int[] rank;
    }

    this (int n) {
        N = n;
        p = iota(N).array;
        rank = new int[](N);
    }

    int find_root(int x) {
        if (p[x] != x) {
            p[x] = find_root(p[x]);
        }

        return p[x];
    }

    bool same(int x, int y) {
        return find_root(x) == find_root(y);
    }

    void unite(int x, int y) {
        int u = find_root(x), v = find_root(y);

        if (u == v) return;

        if (rank[u] < rank[v]) {
            p[u] = v;
        }
        else {
            p[v] = u;

            if (rank[u] == rank[v]) {
                rank[u]++;
            }
        }
    }
}

void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}

struct Queue(T) {
    private {
        int N, head, tail;
        T[] data;
    }

    this(int n) {
        N = n + 1;
        data = new T[](N);
    }

    bool empty() {
        return head == tail;
    }

    bool full() {
        return (tail + 1) % N == head;
    }

    T front() {
        return data[head];
    }

    void push(T x) {
        assert(!full);
        data[tail++] = x;
        tail %= N;
    }

    void pop() {
        assert(!empty);
        head = (head + 1) % N;
    }

    void clear() {
        head = tail = 0;
    }
}

#!/usr/bin/env dub
/+ dub.sdl:
    name "D"
+/

import std.array;
import std.algorithm;
import std.algorithm.iteration;
import std.conv;
import std.math;
import std.stdio;
import std.string;

void main()
{
    int N;
    long D;
    readf(" %s %s ", N, D);

    long[] A = new long[N];
    foreach (i;0..N) readf(" %s ", A[i]);

    long[] cum = [0];
    foreach(a; A) cum ~= cum[$-1] + a;

    long[] cmax = new long[N+1];
    cmax[N] = cum[N];
    for (int i=N-1;i>=0;i--) {
        cmax[i] = max(cum[i], cmax[i+1]);
    }

    long off = 0;
    int ans = 0;
    foreach(i; 0..N) {
        if (A[i] == 0 && cum[i+1] + off < 0) {
            // add as much as possible
            off = D - cmax[i];
            ++ans;
            if (cum[i+1] + off < 0) {
                writeln(-1);
                return;
            }
        }

        if (cum[i+1] > D) {
            writeln(-1);
            return;
        }
    }

    writeln(ans);
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.datetime.stopwatch;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n, d;
    readf("%s %s", &n, &d);
    readln;

    auto arr = readln.chomp.split.map!(to!int).array;

    long csum = 0;
    int mxval = 0, ans = 0;
    foreach (e; arr) {
        if (e != 0) {
            csum += e;
            mxval = max(e, mxval);
            if (csum > d) {
                ans = -1;
                break;
            }
        } else {
            if (csum >= 0) { continue; }

            long need = -csum;
            if (ans != 0 && mxval + need <= d) {
                mxval += need;
            } else {
                ans += 1;
                mxval = 0;
            }

            csum = 0;
        }
    }

    ans.writeln;
}

#!/usr/bin/env dub
/+ dub.sdl:
    name "D"
+/

import std.array;
import std.algorithm;
import std.algorithm.iteration;
import std.conv;
import std.math;
import std.stdio;
import std.string;

void main()
{
    int N;
    long D;
    readf(" %s %s ", N, D);

    long[] A = new long[N];
    foreach (i;0..N) readf(" %s ", A[i]);

    long[] cum = [0];
    foreach(a; A) cum ~= cum[$-1] + a;

    long[] cmax = new long[N+1];
    cmax[N] = cum[N];
    for (int i=N-1;i>=0;i--) {
        cmax[i] = max(cum[i], cmax[i+1]);
    }

    long off = 0;
    int ans = 0;
    foreach(i; 0..N) {
        if (A[i] == 0 && cum[i+1] + off < 0) {
            // add as much as possible
            off = D - cmax[i];
            ++ans;
            if (cum[i+1] + off < 0) {
                writeln(-1);
                return;
            }
        }

        if (cum[i+1] >= D) {
            writeln(-1);
            return;
        }
    }

    writeln(ans);
}

#!/usr/bin/env dub
/+ dub.sdl:
    name "D"
+/

import std.array;
import std.algorithm;
import std.algorithm.iteration;
import std.conv;
import std.math;
import std.stdio;
import std.string;

void main()
{
    int N;
    long D;
    readf(" %s %s ", N, D);

    long[] A = new long[N];
    foreach (i;0..N) readf(" %s ", A[i]);

    long[] cum = [0];
    foreach(a; A) cum ~= cum[$-1] + a;

    long[] cmax = new long[N+1];
    cmax[N] = cum[N];
    for (int i=N-1;i>=0;i--) {
        cmax[i] = max(cum[i], cmax[i+1]);
    }

    long off = 0;
    int ans = 0;
    foreach(i; 0..N) {
        if (A[i] == 0 && cum[i+1] + off < 0) {
            // add as much as possible
            off = D - cmax[i];
            ++ans;
            if (cum[i+1] + off < 0) {
                writeln(-1);
                return;
            }
        }
    }

    writeln(ans);
}

import core.bitop, std.bitmanip;
import core.checkedint;
import std.algorithm, std.functional;
import std.array, std.container;
import std.bigint;
import std.conv;
import std.datetime.stopwatch;
import std.math, std.numeric;
import std.range, std.range.interfaces;
import std.stdio, std.string;
import std.typecons;

void main()
{
    int n, d;
    readf("%s %s", &n, &d);
    readln;

    auto arr = readln.chomp.split.map!(to!int).array;

    long csum = 0;
    int mxval = 0, ans = 0;
    foreach (e; arr) {
        if (e != 0) {
            csum += e;
            mxval = max(e, mxval);
            if (mxval > d) {
                ans = -1;
                break;
            }
        } else {
            if (csum >= 0) { continue; }

            long need = -csum;
            if (ans != 0 && mxval + need <= d) {
                mxval += need;
            } else {
                ans += 1;
                mxval = 0;
            }

            csum = 0;
        }
    }

    ans.writeln;
}

import std.stdio, std.string, std.conv, std.algorithm, std.numeric;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

immutable inf = 10^^9 + 7;

void main() {
    int n, d;
    scan(n, d);
    auto a = readln.split.to!(int[]);

    long bank;
    int ans;

    foreach (i ; 0 .. n) {
        if (a[i] == 0) {
            if (bank < 0) {
                ans++;
                bank = 0;
            }
        }

        bank += a[i];

        debug {
            writeln(bank);
        }

        if (bank > d) {
            writeln(-1);
            return;
        }
    }

    writeln(ans);
}

struct UnionFind {
    private {
        int N;
        int[] p;
        int[] rank;
    }

    this (int n) {
        N = n;
        p = iota(N).array;
        rank = new int[](N);
    }

    int find_root(int x) {
        if (p[x] != x) {
            p[x] = find_root(p[x]);
        }

        return p[x];
    }

    bool same(int x, int y) {
        return find_root(x) == find_root(y);
    }

    void unite(int x, int y) {
        int u = find_root(x), v = find_root(y);

        if (u == v) return;

        if (rank[u] < rank[v]) {
            p[u] = v;
        }
        else {
            p[v] = u;

            if (rank[u] == rank[v]) {
                rank[u]++;
            }
        }
    }
}

void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}

struct Queue(T) {
    private {
        int N, head, tail;
        T[] data;
    }

    this(int n) {
        N = n + 1;
        data = new T[](N);
    }

    bool empty() {
        return head == tail;
    }

    bool full() {
        return (tail + 1) % N == head;
    }

    T front() {
        return data[head];
    }

    void push(T x) {
        assert(!full);
        data[tail++] = x;
        tail %= N;
    }

    void pop() {
        assert(!empty);
        head = (head + 1) % N;
    }

    void clear() {
        head = tail = 0;
    }
}

import std.stdio, std.string, std.conv, std.algorithm, std.numeric;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

immutable inf = 10^^9 + 7;

void main() {
    int n, d;
    scan(n, d);
    auto a = readln.split.to!(int[]);

    auto rw = new long[](n + 1);
    foreach (i ; 1 .. n + 1) {
        rw[i] = rw[i-1] + a[i-1];
    }

    auto rm = new long[](n + 1);
    rm[n] = a[n-1];

    foreach_reverse (i ; 1 .. n) {
        rm[i] = max(rm[i + 1], a[i-1]);
    }

    debug {
        writeln(rw);
        writeln(rm);
    }

    int ans;
    long bank;

    foreach (i ; 0 .. n) {
        if (a[i] == 0 && bank < 0) {
            ans++;
            bank = d - rm[i+1];

            if (bank < 0) {
                writeln(-1);
                return;
            }
        }

        bank += a[i];

        debug {
            writeln(bank);
        }

        if (bank > d) {
            writeln(-1);
            return;
        }
    }

    writeln(ans);
}

struct UnionFind {
    private {
        int N;
        int[] p;
        int[] rank;
    }

    this (int n) {
        N = n;
        p = iota(N).array;
        rank = new int[](N);
    }

    int find_root(int x) {
        if (p[x] != x) {
            p[x] = find_root(p[x]);
        }

        return p[x];
    }

    bool same(int x, int y) {
        return find_root(x) == find_root(y);
    }

    void unite(int x, int y) {
        int u = find_root(x), v = find_root(y);

        if (u == v) return;

        if (rank[u] < rank[v]) {
            p[u] = v;
        }
        else {
            p[v] = u;

            if (rank[u] == rank[v]) {
                rank[u]++;
            }
        }
    }
}

void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}

struct Queue(T) {
    private {
        int N, head, tail;
        T[] data;
    }

    this(int n) {
        N = n + 1;
        data = new T[](N);
    }

    bool empty() {
        return head == tail;
    }

    bool full() {
        return (tail + 1) % N == head;
    }

    T front() {
        return data[head];
    }

    void push(T x) {
        assert(!full);
        data[tail++] = x;
        tail %= N;
    }

    void pop() {
        assert(!empty);
        head = (head + 1) % N;
    }

    void clear() {
        head = tail = 0;
    }
}

import std.stdio, std.string, std.conv, std.algorithm, std.numeric;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

immutable inf = 10^^9 + 7;

void main() {
    int n, d;
    scan(n, d);
    auto a = readln.split.to!(int[]);

    auto rw = new long[](n + 1);
    foreach (i ; 1 .. n + 1) {
        rw[i] = rw[i-1] + a[i-1];
    }

    auto rm = new long[](n + 1);
    rm[n] = a[n-1];

    foreach_reverse (i ; 1 .. n) {
        rm[i] = max(rm[i + 1], a[i-1]);
    }

    debug {
        writeln(rw);
        writeln(rm);
    }

    int ans;
    long bank;

    foreach (i ; 0 .. n) {
        if (a[i] == 0 && bank < 0) {
            ans++;
            bank = d - rm[i];

            if (bank < 0) {
                writeln(-1);
                return;
            }
        }

        bank += a[i];

        debug {
            writeln(bank);
        }

        if (bank > d) {
            writeln(-1);
            return;
        }
    }

    writeln(ans);
}

struct UnionFind {
    private {
        int N;
        int[] p;
        int[] rank;
    }

    this (int n) {
        N = n;
        p = iota(N).array;
        rank = new int[](N);
    }

    int find_root(int x) {
        if (p[x] != x) {
            p[x] = find_root(p[x]);
        }

        return p[x];
    }

    bool same(int x, int y) {
        return find_root(x) == find_root(y);
    }

    void unite(int x, int y) {
        int u = find_root(x), v = find_root(y);

        if (u == v) return;

        if (rank[u] < rank[v]) {
            p[u] = v;
        }
        else {
            p[v] = u;

            if (rank[u] == rank[v]) {
                rank[u]++;
            }
        }
    }
}

void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}

struct Queue(T) {
    private {
        int N, head, tail;
        T[] data;
    }

    this(int n) {
        N = n + 1;
        data = new T[](N);
    }

    bool empty() {
        return head == tail;
    }

    bool full() {
        return (tail + 1) % N == head;
    }

    T front() {
        return data[head];
    }

    void push(T x) {
        assert(!full);
        data[tail++] = x;
        tail %= N;
    }

    void pop() {
        assert(!empty);
        head = (head + 1) % N;
    }

    void clear() {
        head = tail = 0;
    }
}


// tested by Hightail - https://github.com/dj3500/hightail
import std.stdio, std.string, std.conv, std.algorithm;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

int n, m;
int[][] a;

void main() {
    scan(n, m);
    int lim = 2 * max(n, m);
    a = new int[][](lim + 1, lim + 1);
    iota(1, n + 1).each!(i => a[i][1 .. m + 1] = readln.chomp.map!(b => (b - '0').to!int).array);

    debug {
        writefln("%(%(%s %)\n%)", a);
        writeln();
    }

    foreach (i ; 1 .. lim + 1) {
        foreach (j ; 1 .. lim + 1) {
            a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
        }
    }

    debug {
        writefln("%(%(%s %)\n%)", a);
        writeln();
    }

    long ans = 4L * n * m;

    foreach (k ; 2 .. max(n, m) + 1) {
        long anst = 0;

        foreach (i ; 1 .. (n + k - 1) / k + 1) {
            foreach (j ; 1 .. (m + k - 1) / k + 1) {
                long x = a[i*k][j*k] - a[(i-1)*k][j*k] - a[i*k][(j-1)*k] + a[(i-1)*k][(j-1)*k];
                anst += min(x, k*k - x);
            }
        }

        ans = min(ans, anst);

        debug {
            writefln("k:%d, anst:%d", k, anst);
        }
    }

    writeln(ans);
}

void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}


import std.stdio;
import std.random;
import std.range;
import std.string;

int[26] dsu_arr;
bool[26] seen;

int leader(int i) {
    if (dsu_arr[i] == i) return i;
    return dsu_arr[i] = leader(dsu_arr[i]);
}

void unite(int a, int b) {
    dsu_arr[leader(a)] = leader(b);
}

void main() {
    for (int i = 0; i < 26; i++) dsu_arr[i] = i;
    auto strings = stdin.byLine;
    strings.popFront();
    foreach (line; strings) {
        for (int i = 1; i < line.length; i++) {
            unite(line[i - 1] - 'a', line[i] - 'a');
        }
        foreach (c; line) seen[c - 'a'] = true;
    }

    int t = 0;
    for (int i = 0; i < 26; i++) {
        if (seen[i] && leader(i) == i) t++;
    }

    writeln(t);
}

import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main ()
{
	int n;
	while (readf (" %s", &n) > 0)
	{
		readln;
		auto s = new string [n];
		foreach (ref line; s)
		{
			line = readln.strip;
		}
		int [char] pos;
		foreach (i, ref line; s)
		{
			foreach (const ref char c; line)
			{
				pos[c] = i;
			}
		}

		auto p = n.iota.array;
		auto r = new int [n];

		int root (int v)
		{
			if (p[v] == v)
			{
				return v;
			}
			return p[v] = root (p[v]);
		}

		bool unite (int u, int v)
		{
			u = root (u);
			v = root (v);
			if (u == v)
			{
				return false;
			}
			if (r[u] > r[v])
			{
				swap (u, v);
			}
			p[u] = v;
			if (r[u] == r[v])
			{
				r[v] += 1;
			}
			return true;
		}

		int res = n;
		foreach (i, ref line; s)
		{
			foreach (const ref char c; line)
			{
				if (unite (i, pos[c]))
				{
					res -= 1;
				}
			}
		}
		writeln (res);
	}
}

import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string rstring(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T rtype(T)(){ return rstring.to!T; } alias rint = rtype!int, rlong = rtype!long, rreal = rtype!real;
T[] rtypes(T)(int n){ return n.iota.map!(i => rtype!T()).array; } alias rint = rtypes!int, rlong = rtypes!long, rreal = rtypes!real;
T[][] rtypess(T)(int n, int m){ return n.iota.map!(i => rtypes!T(m)).array; } alias rint = rtypess!int, rlong = rtypess!long, rreal = rtypess!real;
T chmin(T)(ref T x, T y){ if(x > y) x = y; return x; } T chmax(T)(ref T x, T y){ if(x < y) x = y; return x; }

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int n = rint;
	string[] ps;
	foreach(i; 0 .. n) ps ~= rstring;

	Node[] nodes;
	Node[int] letternodes;
	foreach(i; 0 .. 26){
		Node nd = new Node(i, 1);
		nodes ~= nd;
		letternodes['a' + i] = nd;
	}

	Edge[] edges;
	foreach(i, p; ps){
		Node nd = new Node(26 + i, 0);
		nodes ~= nd;
		foreach(c; p) edges ~= new Edge(nd, letternodes[c], 0);
	}

	foreach(ed; edges) ed.node1.group.eat(ed.node2.group);

	int ans;
	foreach(nd; nodes) if(nd.value == 0 && nd.group.id == nd.id) ans += 1;

	ans.writeln;
}
class Edge{
	Node node1;
	Node node2;
	long value;
	this(Node node1, Node node2, long value){
		this.node1 = node1, this.node2 = node2;
		this.value = value;
	}
}

class Node{
	long id;
	long value;
	Group group;
	this(long id, long value){
		this.id = id;
		this.value = value;
		this.group = new Group(this);
	}
}

class Group{
	long value;
	long id;
	Node[] nodes;
	this(Node node){
		this.id = node.id;
		this.nodes = [node];
		this.value = node.value;
	}
	void eat(Group gp){
		if(this.id == gp.id) return;
		if(gp.nodes.length > this.nodes.length) gp.eat(this);
		else{
			foreach(nd; gp.nodes){
				this.nodes ~= nd;
				nd.group = this;
				this.value += nd.value;
			}
		}
	}
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
long lcm(long x, long y) { return x * (y / gcd(x, y)); }

//long mod = 10^^9 + 7;
long mod = 998244353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }

struct UnionFind
{
	void init(int n) { par = new int[](n); foreach (i; 0..n) par[i] = i; cnt = new int[](n); fill(cnt, 1); }
	int root(int i) { return par[i] == i ? i : (par[i] = root(par[i])); }
	bool same(int i, int j) { return root(i) == root(j); }
	void unite(int i, int j) { i = root(i); j = root(j); if (i == j) return; par[i] = j; cnt[j] += cnt[i]; }
	int size(int i) { return cnt[root(i)]; }
	int[] par, cnt;
}

void main()
{
	auto n = RD!int;

	UnionFind uf;
	uf.init(26);
	auto used = new bool[](26);
	foreach (i; 0..n)
	{
		auto s = RD!string;
		foreach (j; 0..s.length)
		{
			auto u = s[j]-'a';
			used[u] = true;
			foreach (k; j+1..s.length)
			{
				auto v = s[k]-'a';
				used[v] = true;
				uf.unite(u, v);
			}
		}
	}

	bool[int] set;
	foreach (i; 0..26)
	{
		if (!used[i]) continue;
		auto p = uf.root(i);
		set[p] = true;
	}
	writeln(set.keys.length);
	stdout.flush;
	debug readln;
}


import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static string[] s_rd;
T RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
string RDR()() { return readln.chomp; }
T[] ARR(T = long)(in string str, T fix = 0) { auto r = str.split.to!(T[]); r[] += fix; return r; }
T[] RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[][] RDA2(T = long)(size_t n, T[] fix = []) { auto r = new T[][](n); foreach (i; 0..n) { r[i] = readln.chomp.split.to!(T[]); foreach (j, e; fix) r[i][j] += e; } return r; }
size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
long lcm(long x, long y) { return x * y / gcd(x, y); }

//long mod = 10^^9 + 7;
long mod = 998_244_353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }

void main()
{
	auto n = RD!int;
	auto ans = new char[][](n, n);
	ans[0][0] = 'W';
	ans[0][1] = 'B';
	ans[0][2] = 'W';
	ans[1][0] = 'B';
	ans[2][0] = 'W';
	ans[1][1] = 'W';

	bool visit(int y, int x, int c)
	{
		bool ok;
		if (inside(y, 0, n) && inside(x, 0, n))
		{
			if (ans[y][x] == char.init)
			{
				ans[y][x] = c == 0 ? 'B' : 'W';
				ok = true;
			}
		}
		return ok;
	}

	int[3][] open = [[0,0,0], [0,1,1], [0,2,0], [1,0,1], [2,0,0], [1,1,0]];
	while (!open.empty)
	{
		auto node = open.front; open.popFront;
		auto y = node[0];
		auto x = node[1];
		auto c = node[2];
		if (visit   (y-1, x-2, c))
			open ~= [y-1, x-2, c^1];
		if (visit   (y+1, x-2, c))
			open ~= [y+1, x-2, c^1];
		if (visit   (y-1, x+2, c))
			open ~= [y-1, x+2, c^1];
		if (visit   (y+1, x+2, c))
			open ~= [y+1, x+2, c^1];
		if (visit   (y-2, x-1, c))
			open ~= [y-2, x-1, c^1];
		if (visit   (y-2, x+1, c))
			open ~= [y-2, x+1, c^1];
		if (visit   (y+2, x-1, c))
			open ~= [y+2, x-1, c^1];
		if (visit   (y+2, x+1, c))
			open ~= [y+2, x+1, c^1];
	}

	foreach (y; 0..n)
	{
		writeln(ans[y]);
	}
	stdout.flush();
	debug readln();
}

import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); }
void log()(){ writeln(""); } void log(T, A ...)(T t, lazy A a){ if(DEBUG) write(t, " "), log(a); } bool DEBUG = 0;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T rtype(T)(){ return read.to!T; } alias rint = rtype!int, rlong = rtype!long, rreal = rtype!real;
T[] rtypes(T)(int n){ return n.iota.map!(i => rtype!T()).array; } alias rint = rtypes!int, rlong = rtypes!long, rreal = rtypes!real;
T[][] rtypess(T)(int n, int m){ return n.iota.map!(i => rtypes!T(m)).array; } alias rint = rtypess!int, rlong = rtypess!long, rreal = rtypess!real;

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int n = rint;
	foreach(i; 0 .. n){
		foreach(j; 0 .. n){
			if((i + j) % 2) "B".write;
			else "W".write;
		}
		"".writeln;
	}
}


@safe:
import std;

T read (alias T, string ending = "", string preface = "") () @trusted {
    scope T x;
    readf!(preface ~ "%s" ~ ending)(x);
    return x;
}

void main () {
    immutable tests = read!(uint, "\n");

    foreach (test_index; 0 .. tests) {
        immutable l = read!(uint, " ");
        immutable r = read!(uint, " ");
        immutable k = read!(uint, "\n");

        if (r == l) {
            if (r == 1) {
                writeln("NO");
            } else {
                writeln("YES");
            }
            continue;
        }

        immutable count_div_by_2 = (){
            static assert(true);
            if (r % 2 == l % 2) {
                if (r % 2 == 0) {
                    return (r - l) / 2 + 1;
                } else {
                    return (r - l) / 2;
                }
            }
            return (r - l + 1) / 2;
        }();

        immutable count_not_div_by_2 = r - l + 1 - count_div_by_2;

        if (k >= count_not_div_by_2) {
            writeln("YES");
        } else {
            writeln("NO");
        }
    }
}
// ""

import std;

T read (alias T, string ending = "", string preface = "") () {
    scope T x;
    readf!(preface ~ "%s" ~ ending)(x);
    return x;
}

void main () {
    immutable tests = read!(uint, "\n");

    foreach (test_index; 0 .. tests) {
        immutable l = read!(uint, " ");
        immutable r = read!(uint, " ");
        immutable k = read!(uint, "\n");

        if (r == l) {
            if (r == 1) {
                writeln("NO");
            } else {
                writeln("YES");
            }
            continue;
        }

        immutable count_div_by_2 = (){
            static assert(true);
            if (r % 2 == l % 2) {
                if (r % 2 == 0) {
                    return (r - l) / 2 + 1;
                } else {
                    return (r - l) / 2;
                }
            }
            return (r - l + 1) / 2;
        }();

        immutable count_not_div_by_2 = r - l + 1 - count_div_by_2;

        if (k >= count_not_div_by_2) {
            writeln("YES");
        } else {
            writeln("NO");
        }
    }
}
// ""

void main() { runSolver(); }

void problem() {
  auto QN = scan!int;

  auto solve() {
    auto subSolve() {
      auto L = scan!int;
      auto R = scan!int;
      auto K = scan!int;

      const evens = R/2 - (L-1)/2;
      const odds = R - L + 1 - evens;
      // [evens, odds].deb;

      if (R == L && L == 1) return "NO";
      if (R == L && L >  1) return "YES";

      return evens > 0 && odds <= K ? "YES" : "NO";
    }

    foreach(i; 0..QN) {
      subSolve().writeln;
    }
  }

  outputForAtCoder(&solve);
}

// ----------------------------------------------

import std.stdio, std.conv, std.array, std.string, std.algorithm, std.container, std.range, core.stdc.stdlib, std.math, std.typecons, std.numeric, std.traits, std.functional, std.bigint, std.datetime.stopwatch, core.time, core.bitop;
T[][] combinations(T)(T[] s, in long m) {   if (!m) return [[]];   if (s.empty) return [];   return s[1 .. $].combinations(m - 1).map!(x => s[0] ~ x).array ~ s[1 .. $].combinations(m); }
string scan(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T scan(T)(){ return scan.to!T; }
T[] scan(T)(long n){ return n.iota.map!(i => scan!T()).array; }
void deb(T ...)(T t){ debug writeln(t); }
alias Point = Tuple!(long, "x", long, "y");
Point invert(Point p) { return Point(p.y, p.x); }
long[] divisors(long n) { long[] ret; for (long i = 1; i * i <= n; i++) { if (n % i == 0) { ret ~= i; if (i * i != n) ret ~= n / i; } } return ret.sort.array; }
bool chmin(T)(ref T a, T b) { if (b < a) { a = b; return true; } else return false; }
bool chmax(T)(ref T a, T b) { if (b > a) { a = b; return true; } else return false; }
string charSort(alias S = "a < b")(string s) { return (cast(char[])((cast(byte[])s).sort!S.array)).to!string; }
ulong comb(ulong a, ulong b) { if (b == 0) {return 1;}else{return comb(a - 1, b - 1) * a / b;}}
T[] compress(T)(T[] arr, T origin = T.init) { T[T] indecies; arr.dup.sort.uniq.enumerate(origin).each!((i, t) => indecies[t] = i); return arr.map!(t => indecies[t]).array; }
string toAnswerString(R)(R r) { return r.map!"a.to!string".joiner(" ").array.to!string; }
struct ModInt(uint MD) if (MD < int.max) {ulong v;this(string v) {this(v.to!long);}this(int v) {this(long(v));}this(long v) {this.v = (v%MD+MD)%MD;}void opAssign(long t) {v = (t%MD+MD)%MD;}static auto normS(ulong x) {return (x<MD)?x:x-MD;}static auto make(ulong x) {ModInt m; m.v = x; return m;}auto opBinary(string op:"+")(ModInt r) const {return make(normS(v+r.v));}auto opBinary(string op:"-")(ModInt r) const {return make(normS(v+MD-r.v));}auto opBinary(string op:"*")(ModInt r) const {return make((ulong(v)*r.v%MD).to!ulong);}auto opBinary(string op:"^^", T)(T r) const {long x=v;long y=1;while(r){if(r%2==1)y=(y*x)%MD;x=x^^2%MD;r/=2;} return make(y);}auto opBinary(string op:"/")(ModInt r) const {return this*memoize!inv(r);}static ModInt inv(ModInt x) {return x^^(MD-2);}string toString() const {return v.to!string;}auto opOpAssign(string op)(ModInt r) {return mixin ("this=this"~op~"r");}}
alias MInt1 = ModInt!(10^^9 + 7);
alias MInt9 = ModInt!(998_244_353);
void outputForAtCoder(T)(T delegate() fn) {
  static if (is(T == float) || is(T == double) || is(T == real)) "%.16f".writefln(fn());
  else static if (is(T == void)) fn();
  else static if (is(T == string)) fn().writeln;
  else static if (isInputRange!T) {
    static if (!is(string == ElementType!T) && isInputRange!(ElementType!T)) foreach(r; fn()) r.toAnswerString.writeln;
    else foreach(r; fn()) r.writeln;
  }
  else fn().writeln;
}
void runSolver() {
  enum BORDER = "==================================";
  debug { BORDER.writeln; while(!stdin.eof) { "<<< Process time: %s >>>".writefln(benchmark!problem(1)); BORDER.writeln; } }
  else problem();
}
enum YESNO = [true: "Yes", false: "No"];

// -----------------------------------------------

struct GridPoint {
  static enum ZERO = GridPoint(0, 0);
  long x, y;

  static GridPoint reversed(long y, long x) {
    return GridPoint(x, y);
  }

  this(long x, long y) {
    this.x = x;
    this.y = y;
  }

  inout GridPoint left() { return GridPoint(x - 1, y); }
  inout GridPoint right() { return GridPoint(x + 1, y); }
  inout GridPoint up() { return GridPoint(x, y - 1); }
  inout GridPoint down() { return GridPoint(x, y + 1); }
  inout GridPoint leftUp() { return GridPoint(x - 1, y - 1); }
  inout GridPoint leftDown() { return GridPoint(x - 1, y + 1); }
  inout GridPoint rightUp() { return GridPoint(x + 1, y - 1); }
  inout GridPoint rightDown() { return GridPoint(x + 1, y + 1); }
  inout GridPoint[] around() { return [left(), up(), right(), down()]; }
  inout GridPoint[] around(GridPoint max) { GridPoint[] ret; if (x > 0) ret ~= left; if(x < max.x-1) ret ~= right; if(y > 0) ret ~= up; if(y < max.y-1) ret ~= down; return ret; }
  inout T of(T)(inout ref T[][] grid) { return grid[cast(int)y][cast(int)x]; }
}

// Cheese-Cracker: cheese-cracker.github.io

void solve(){
    long l = scan; long r = scan; long k = scan;
    long len = r - l + 1;
    if(len == 1){
        writeln( (l == 1) ? "NO" : "YES");
        return;
    }

    long tim = len / 2;
    if(r % 2 == 1 && l % 2 == 1){ tim += 1; }
    writeln( (k >= tim) ? "YES" : "NO");
}

void main(){
    long tests = scan;        // Toggle!
    while(tests--) solve;
}

/**************    *****    That's All Folks!    *****    **************/
import std.stdio, std.range, std.conv, std.typecons, std.algorithm, std.container, std.math, std.numeric;
string[] tk; T scan(T=long)(){while(!tk.length)tk = readln.split; string a=tk.front; tk.popFront; return a.to!T;}
T[] scanArray(T=long)(){ auto r = readln.split.to!(T[]); return r; }
void show(A...)(A a){ debug{ foreach(t; a){stderr.write(t, "| ");} stderr.writeln; } }
alias ll = long, tup = Tuple!(long, "x",  long, "y");


import std.stdio;
import std.range;
import std.typecons;
import std.algorithm;

void main()
{
	byte n, m;

	readf(" %s %s", &n, &m);

	foreach (i; 0..n) {
		foreach (j; 0..m)
			if (i % 2) {
				foreach (k; 0..m - 1) {
					static byte tmp = 3;
					auto temp = i;
					if (temp == tmp) {
						write('#');
						foreach (l; 0..m - 1)
							write('.');
						tmp += 4;
						break;
					}
					else {
						write('.');
						if (k == m - 2)
							write('#');
					}
				}
				break;
			}
			else
				write('#');
		writeln();
	}
}

module _template;
import std.stdio;
import std.string;
import std.algorithm;
import std.container;
import std.range;
import std.math;
import std.numeric;
import std.conv;
import std.typecons;
import std.format;

struct IO {
        string read_string() {
                while (tokens.empty) {
                tokens = readln.split;
        }
        auto token = tokens.front;
                tokens.popFront;
                return token;
        }

        int read_int() {
                return read_string.to!int;
        }

        double read_double() {
                return read_string.to!double;
        }

        string[] tokens;
}

void main() {
        IO cin;
        int t = 1;
        // int t = cin.read_int;
        while (t--) {
                int n, m;
                n = cin.read_int;
                m = cin.read_int;

                for (int i = 0; i < n; i++) {
                        for (int j = 0; j < m; j++) {
                                if (i % 2 == 0) {
                                        write("#");
                                } else {
                                        if (i % 4 == 1) {
                                                if (j < m - 1) write(".");
                                                else write("#");
                                        } else {
                                                if (j == 0) write("#");
                                                else write(".");
                                        }
                                }
                        }
                        writeln();
                }
        }
}

import std.stdio, std.array, std.conv;

void main(string[] args)
{
	int n, m;
	readf(" %s %s", &n, &m);

	char ch = '#';
	string snake = to!string(ch).replicate(m);
	string points = ".".replicate(m-1);

	foreach(row; 1..n+1)
		if(row % 2)
			writeln(snake);
		else if(row % 4)
			writeln(points ~ ch);
		else
			writeln(ch ~ points);
}

import std.stdio: writeln, stdin;
import std.string: strip;
import std.algorithm.iteration : map;
import std.regex;
import std.range;
import std.conv;

void main()
{
  auto nm = stdin.readln.strip.split(regex(` +`)).map!(to!int);
  auto n=nm[0], m=nm[1];
  auto p1 = '#'.repeat().take(m).to!string;
  auto p23 = '.'.repeat().take(m-1).to!string;
  auto p2 = "#"~p23;
  auto p3 = p23~"#";

  for(int i = 1; i <= n; i++) {
    writeln( (i%2!=0) ? p1
            :(i/2)%2==0 ? p2
            : p3);
  }
}

import std.stdio;

int main()
{
	int n, m;
	readf("%d %d", &n, &m);
	char[] ol = new char[m];
	char[] el = new char[m];
	foreach (int i; 0..m)
	{
		ol[i] = '#';
		el[i] = '.';
	}
	foreach (int i; 0..n)
	{
		int idx = (i / 2) % 2 == 0 ? m-1 : 0;
		el[idx] = '#';
		write((i % 2 == 0 ? ol : el) ~ "\n");
		el[idx] = '.';
	}
	return 0;
}

import std.stdio;

void main() {
    int n, m;
    readf("%d %d\n", &n, &m);

    for (int i = 0; i < n; i++) {
        if (i % 2 == 0) {
            for (int j = 0; j < m; j++) {
                write("#");
            }
        } else if (i % 4 == 1) {
            for (int j = 0; j < m - 1; j++) {
                write(".");
            }
            write("#");
        } else {
            write("#");
            for (int j = 0; j < m - 1; j++) {
                write(".");
            }
        }

        writeln;
    }
}


import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.split.map!(to!int).array;

    debug { a.writeln; }

    bool [int] v;
    a.each!(x => v[x] = true);

    int[] getAns(int x) {
        int ans = 0;
        auto powersOf2 = recurrence!((a, n) => a[n-1] * 2)(1U);
        foreach (p; powersOf2.until!(x => x > 10^^9 * 2)) {
            auto left = x - cast(int)p in v;
            auto right = x + cast(int)p in v;
            if (left && right) {
                ans = p;
                break;
            }
            if (left || right) ans = p;
        }

        if (ans == 0) return [x];

        auto ret = [x];
        if (x - ans in v) ret ~= x - ans;
        if (x + ans in v) ret ~= x + ans;
        return ret;
    }

    auto ans = a.map!(e => getAns(e)).maxElement!(e => e.length);

    ans.length.writeln;
    ans.writefln!("%(%s %)");
}

import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop, std.bitmanip;

void main() {
    auto N = readln.chomp.to!int;
    auto A = readln.split.map!(to!long).array;
    A.sort();

    bool[long] D;
    foreach (i; 0..N) {
        D[A[i]] = true;
    }

    int max_v = 1;
    long[] ans = [A[0]];

    foreach (a; A) {
        for (long d = 1; d < 10L^^10; d *= 2) {
            if ((a + d) in D && (a + 2*d) in D) {
                writeln(3);
                writeln(a, " ", a+d, " ", a+2*d);
                return;
            } else if (max_v == 1 && (a + d) in D) {
                max_v = 2;
                ans = [a, a+d];
            }
        }
    }

    max_v.writeln;
    ans.map!(to!string).join(" ").writeln;
}

import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.split.map!(to!int).array;

    debug { a.writeln; }

    bool [int] v;
    a.each!(x => v[x] = true);

    int[] getAns(int x) {
        int ans = 0;
        uint p = 1;
        while (p <= 10^^9 * 2) {
            auto left = x - cast(int)p in v;
            auto right = x + cast(int)p in v;
            if (left && right) {
                ans = p;
                break;
            }
            if (left || right) ans = p;

            p *= 2;
        }

        if (ans == 0) return [x];

        auto ret = [x];
        if (x - ans in v) ret ~= x - ans;
        if (x + ans in v) ret ~= x + ans;
        return ret;
    }

    auto ans = a.map!(e => getAns(e)).maxElement!(e => e.length);

    ans.length.writeln;
    ans.writefln!("%(%s %)");
}

import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.split.map!(to!int).array;

    debug { a.writeln; }

    bool [int] v;
    a.each!(x => v[x] = true);

    int[] getAns(int x) {
        int ans = 0;
        auto powersOf2 = recurrence!(q{ a[n-1] * 2 })(1U);
        foreach (p; powersOf2.until!(x => x > 10^^9 * 2)) {
            auto left = x - cast(int)p in v;
            auto right = x + cast(int)p in v;
            if (left && right) {
                ans = p;
                break;
            }
            if (left || right) ans = p;
        }

        if (ans == 0) return [x];

        auto ret = [x];
        if (x - ans in v) ret ~= x - ans;
        if (x + ans in v) ret ~= x + ans;
        return ret;
    }

    auto ans = a.map!(e => getAns(e)).maxElement!(e => e.length);

    ans.length.writeln;
    ans.writefln!("%(%s %)");
}

import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.split.map!(to!int).array;

    debug { a.writeln; }

    bool [int] v;
    a.each!(x => v[x] = true);

    int[] getAns(int x) {
        int ans = 0;
        uint p = 1;
        while (p <= 10^^9 * 2) {
            auto left = (x - cast(int)p) in v;
            auto right = (x + cast(int)p) in v;
            if (left && right) {
                ans = p;
                break;
            }
            if (left || right) ans = cast(int)p;

            p *= 2;
        }

        if (ans == 0) return [x];

        auto ret = [x];
        if (x - ans in v) ret ~= x - ans;
        if (x + ans in v) ret ~= x + ans;
        return ret;
    }

    int[] ans = [];
    foreach (e; a) {
        auto cur = getAns(e);
        if (cur.length > ans.length) ans = cur;
    }

    ans.length.writeln;
    ans.writefln!("%(%s %)");
}

import std.stdio;
import std.algorithm;
import std.container.rbtree;
import std.algorithm.comparison : equal;

int main()
{
	int n;
	scanf("%d",&n);

	auto arr = new long[n];

	for(int i = 0; i < n; i++)
		scanf("%lld", &arr[i]);

	auto rbt = redBlackTree(arr);

	long[] subset = [arr[0]];

	for(int i = 0; i < n; i++)
	{
		for(long d = 1; d < (1L << 31); d*= 2)
		{
			if(!rbt.equalRange(arr[i] + d).empty()) {
				if (!rbt.equalRange(arr[i] + d * 2).empty()) {
					printf("3\n");
					printf("%lld %lld %lld\n",arr[i], arr[i] + d, arr[i] + 2 * d);
					return 0;
				}

				subset = [arr[i], arr[i] + d];
			}
		}
	}

	printf("%d\n",subset.length);

	for(int i =0; i < subset.length;i++)
		printf("%lld ",subset[i]);

	return 0;
}

void main(){
  import std.stdio, std.algorithm, std.string, std.conv;

  int n; rd(n);
  auto a=readln.split.to!(long[]);

  sort(a);
  import std.range;
  auto p=a.assumeSorted;
  long[] ans;
  foreach(b; 0..31){
    long d=1L<<b;
    auto used=new bool[](n);
    foreach(int i; 0..n){
      if(used[i]) continue;
      used[i]=true;
      int j=i;
      long[] beta=[a[j]];
      while(j<n){
        auto tri=p.trisect(a[j]+d);
        if(tri[1].empty){
          break;
        }else{
          j=tri[0].length.to!(int);
          beta~=a[j];
          used[j]=true;
        }
        if(beta.length==3) break;
      }
      if(ans.length<beta.length) ans=beta.dup;
    }
  }
  writeln(ans.length);
  writefln("%(%s %)", ans);
}

void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x) e=l[i].to!(typeof(e));
}

import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
    readln;

    auto a = readln.chomp.split.map!(to!int).array;

    debug { a.writeln; }

    bool [int] v;
    a.each!(x => v[x] = true);

    int[] getAns(int x) {
        int ans = 0;
        auto powersOf2 = recurrence!(q{ a[n-1] * 2 })(1U);
        foreach (p; powersOf2.until!(x => x <= 10^^9 * 2)) {
            auto left = x - cast(int)p in v;
            auto right = x + cast(int)p in v;
            if (left && right) {
                ans = p;
                break;
            }
            if (left || right) ans = p;
        }

        if (ans == 0) return [x];

        auto ret = [x];
        if (x - ans in v) ret ~= x - ans;
        if (x + ans in v) ret ~= x + ans;
        return ret;
    }

    auto ans = a.map!(e => getAns(e)).maxElement!(e => e.length);

    ans.length.writeln;
    ans.writefln!("%(%s %)");
}

void main(){
  import std.stdio, std.algorithm, std.string, std.conv;

  int n; rd(n);
  auto a=readln.split.to!(long[]);
  sort(a);

  import std.range;
  auto p=a.assumeSorted;
  long[] ans;
  foreach(b; 0..31){
    long d=1L<<b;
    auto used=new bool[](n);
    foreach(i; 0..n){
      if(used[i]) continue;
      used[i]=true;
      int j=i, cnt=1;
      long[] beta=[a[i]];
      while(j<n){
        auto tri=p.trisect(a[j]+d);
        if(tri[1].empty){
          break;
        }else{
          cnt++;
          j=tri[0].length.to!(int);
          used[j]=true;
          beta~=a[j];
        }
      }
      if(ans.length<beta.length) ans=beta.dup;
    }
  }

  writeln(ans.length);
  writefln("%(%s %)", ans);
}

void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x) e=l[i].to!(typeof(e));
}

void main(){
  import std.stdio, std.algorithm, std.string, std.conv;

  int n; rd(n);
  auto a=readln.split.to!(long[]);

  sort(a);
  import std.range;
  auto p=a.assumeSorted;
  long[] ans;
  foreach(b; 0..31){
    long d=1L<<b;
    auto used=new bool[](n);
    foreach(int i; 0..n){
      if(used[i]) continue;
      used[i]=true;
      int j=i;
      long[] beta=[a[j]];
      while(j<n){
        auto tri=p.trisect(a[j]+d);
        if(tri[1].empty){
          break;
        }else{
          j=tri[0].length.to!(int);
          beta~=a[j];
          used[j]=true;
        }
      }
      if(ans.length<beta.length){
        ans=beta.dup;
        if(ans.length==3){
          writeln(ans.length);
          writefln("%(%s %)", ans);
          return;
        }
      }
    }
  }
  writeln(ans.length);
  writefln("%(%s %)", ans);
}

void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x) e=l[i].to!(typeof(e));
}

void main(){
  import std.stdio, std.algorithm, std.string, std.conv;
  import std.random;

  int n; rd(n);
  auto a=readln.split.to!(long[]);

  // int n=15;
  // long[] a;
  // bool[long] h;
  // foreach(_; 0..n){
  //   long e=uniform(-100, 100);
  //   while(e in h){
  //     e=uniform(-100, 100);
  //   }
  //   a~=e;
  //   h[e]=true;
  // }

  sort(a);
  // writeln(a);

  import std.range;
  import core.bitop;
  auto p=a.assumeSorted;
  long[] ans;
  foreach(b; 0..32){
    long d=1L<<b;
    auto used=new bool[](n);
    foreach(i; 0..n){
      if(used[i]) continue;
      used[i]=true;
      int j=i;
      long[] beta=[a[i]];
      while(j<n){
        auto tri=p.trisect(a[j]+d);
        if(tri[1].empty){
          break;
        }else{
          j=tri[0].length.to!(int);
          used[j]=true;
          beta~=a[j];
        }
      }
      if(ans.length<beta.length){
        if(b==0){
          if(popcnt(beta.length)==1) ans=beta.dup;
        }else{
            ans=beta.dup;
        }
      }
    }
  }

  writeln(ans.length);
  writefln("%(%s %)", ans);

  // solve(a);
}

void solve(long[] a){
  import core.bitop, std.conv, std.math, std.algorithm;
  import std.stdio;
  int n=a.length.to!(int);
  long[] ret;
  foreach(bit; 0..(1<<n)){
    long[] cord;
    foreach(i; 0..n)if(bit&(1<<i)) cord~=a[i];
    int m=cord.length.to!(int);
    foreach(i; 0..m)foreach(j; 0..i){
      long dif=(cord[i]-cord[j]).abs;
      if(popcnt(dif)>1) goto hell;
    }
    if(ret.length<cord.length) ret=cord.dup;
    hell:;
  }
  writeln(ret.length);
  writeln(ret);
}

void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x) e=l[i].to!(typeof(e));
}


import std.algorithm;
import std.c.stdio;
import std.stdio;
import std.conv;
import std.math;
import std.array;
import std.container;

int curc;
bool eof = false;

void sb()
{
    do
    {
        curc = getchar ();
    }
    while (0 <= curc && curc <= 32);
    if (curc == EOF)
    {
        eof = true;
    }
}

char rc ()
{
    sb ();
    return cast (char) curc;
}

int ni ()
{
    sb ();
    int res = 0;
    do
    {
        res = res * 10 + cast (int) (curc - '0');
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

long nl ()
{
    sb ();
    long res = 0;
    do
    {
        res = res * 10 + cast (long) (curc - '0');
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

char[] ns ()
{
    sb ();
    char[] res = [];
    do
    {
        res ~= to!char(curc);
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

void CFBETA142D()
{
    import std.array;
    alias immutable int[] tuple;
    alias int[int] setint;
    alias long[long] setlong;
    long inf = (1L << 63) - 1;
    auto n = ni(), m = ni();
    int[][] g = new int[][](n, 0);
    int[tuple] weights;
    for (int i=0; i<m; ++i)
    {
        auto a = ni() - 1, b = ni() - 1, w = ni();
        weights[cast(tuple)[a,b]] = w;
        weights[cast(tuple)[b,a]] = w;
        g[a] ~= b;
        g[b] ~= a;
    }
    setlong[] t = new setlong[n];
    for (int i=0; i<n-1; ++i)
    {
        auto k = ni();
        int[] tmp = new int[k];
        for (int j = 0; j < k; ++j)
            tmp[j] = ni();
        for (int j = k - 1; j >= 0; --j)
        {
            auto p = (tmp[j] + 1) in t[i];
            if (p is null)
                t[i][tmp[j]] = tmp[j] + 1;
            else
                t[i][tmp[j]] = t[i][tmp[j] + 1];
        }
    }
    long get(long i, long time)
    {
        if ((time in t[cast(uint)i]) is null) return time;
        else return t[cast(uint)i][time];
    }
    long[] planets = new long[n];
    for (auto i=0; i<n; ++i) planets[i] = inf;
    planets[0] = get(0, 0);
    struct S
    {
        int v;
        int opCmp(ref const S s) const
        {
            if (planets[v] == planets[s.v])
                return v - s.v;
            else
                return planets[v] > planets[s.v] ? 1 : -1;
        }
    }
    auto q = redBlackTree!("a < b", true)(cast(S)0);
    while (!q.empty())
    {
        auto v = q.front().v;
        q.removeFront();
        foreach (int to; g[v])
        {
            auto len = weights[cast(tuple)[v, to]];
            if (get(to, planets[v] + len) < planets[to])
            {
                q.removeKey(cast(S)to);
                planets[to] = get(to, planets[v] + len);
                q.insert(cast(S)to);
            }
        }
    }
    writeln(planets[n - 1] == inf ? -1 : planets[n - 1]);
}

void main()
{
    CFBETA142D();
}

import std.algorithm;
import std.c.stdio;
import std.stdio;
import std.conv;
import std.math;
import std.array;
import std.container;

int curc;
bool eof = false;

void sb()
{
    do
    {
        curc = getchar ();
    }
    while (0 <= curc && curc <= 32);
    if (curc == EOF)
    {
        eof = true;
    }
}

char rc ()
{
    sb ();
    return cast (char) curc;
}

int ni ()
{
    sb ();
    int res = 0;
    do
    {
        res = res * 10 + cast (int) (curc - '0');
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

long nl ()
{
    sb ();
    long res = 0;
    do
    {
        res = res * 10 + cast (long) (curc - '0');
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

char[] ns ()
{
    sb ();
    char[] res = [];
    do
    {
        res ~= to!char(curc);
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

void CFBETA142D()
{
    import std.array;
    alias immutable int[] tuple;
    alias int[int] setint;
    alias long[long] setlong;
    long inf = (1L << 63) - 1;
    auto n = ni(), m = ni();
    int[][] g = new int[][](n, 0);
    int[tuple] weights;
    for (int i=0; i<m; ++i)
    {
        auto a = ni() - 1, b = ni() - 1, w = ni();
        weights[cast(tuple)[a,b]] = w;
        weights[cast(tuple)[b,a]] = w;
        g[a] ~= b;
        g[b] ~= a;
    }
    setlong[] t = new setlong[n];
    for (int i=0; i<n-1; ++i)
    {
        auto k = ni();
        int[] tmp = new int[k];
        for (int j = 0; j < k; ++j)
            tmp[j] = ni();
        for (int j = k - 1; j >= 0; --j)
        {
            auto p = (tmp[j] + 1) in t[i];
            if (p is null)
                t[i][tmp[j]] = tmp[j] + 1;
            else
                t[i][tmp[j]] = t[i][tmp[j] + 1];
        }
    }
    long get(long i, long time)
    {
        if ((time in t[cast(uint)i]) is null) return time;
        else return t[cast(uint)i][time];
    }
    long[] planets = new long[n];
    for (auto i=0; i<n; ++i) planets[i] = inf;
    planets[0] = get(0, 0);
    struct S
    {
        int v;
        int opCmp(ref const S s) const
        {
            if (planets[v] == planets[s.v])
                return v - s.v;
            else
                return planets[v] > planets[s.v] ? 1 : -1;
        }
    }
    auto q = redBlackTree!("a < b", false)(cast(S)0);
    while (!q.empty())
    {
        auto v = q.front().v;
        q.removeFront();
        foreach (int to; g[v])
        {
            auto len = weights[cast(tuple)[v, to]];
            if (get(to, planets[v] + len) < planets[to])
            {
                q.removeKey(cast(S)to);
                planets[to] = get(to, planets[v] + len);
                q.insert(cast(S)to);
            }
        }
    }
    writeln(planets[n - 1] == inf ? -1 : planets[n - 1]);
}

void main()
{
    CFBETA142D();
}

import std.algorithm;
import std.c.stdio;
import std.stdio;
import std.conv;
import std.math;
import std.array;
import std.container;

int curc;
bool eof = false;

void sb()
{
    do
    {
        curc = getchar ();
    }
    while (0 <= curc && curc <= 32);
    if (curc == EOF)
    {
        eof = true;
    }
}

char rc ()
{
    sb ();
    return cast (char) curc;
}

int ni ()
{
    sb ();
    int res = 0;
    do
    {
        res = res * 10 + cast (int) (curc - '0');
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

long nl ()
{
    sb ();
    long res = 0;
    do
    {
        res = res * 10 + cast (long) (curc - '0');
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

char[] ns ()
{
    sb ();
    char[] res = [];
    do
    {
        res ~= to!char(curc);
        curc = getchar ();
    }
    while (32 < curc);
    return res;
}

void CFBETA142D()
{
    import std.array;
    alias immutable int[] tuple;
    alias int[int] setint;
    alias long[long] setlong;
    long inf = (1L << 63) - 1;
    auto n = ni(), m = ni();
    int[][] g = new int[][](n, 0);
    int[tuple] weights;
    for (int i=0; i<m; ++i)
    {
        auto a = ni() - 1, b = ni() - 1, w = ni();
        weights[cast(tuple)[a,b]] = w;
        weights[cast(tuple)[b,a]] = w;
        g[a] ~= b;
        g[b] ~= a;
    }
    setlong[] t = new setlong[n];
    for (int i=0; i<n; ++i)
    {
        auto k = ni();
        int[] tmp = new int[k];
        for (int j = 0; j < k; ++j)
            tmp[j] = ni();
        for (int j = k - 1; j >= 0; --j)
        {
            auto p = (tmp[j] + 1) in t[i];
            if (p is null)
                t[i][tmp[j]] = tmp[j] + 1;
            else
                t[i][tmp[j]] = t[i][tmp[j] + 1];
        }
    }
    long get(long i, long time)
    {
        if ((time in t[cast(uint)i]) is null) return time;
        else return t[cast(uint)i][time];
    }
    long[] planets = new long[n];
    for (auto i=0; i<n; ++i) planets[i] = inf;
    planets[0] = t[0] !is null ? t[0][0] : 0;
    struct S
    {
        int v;
        int opCmp(ref const S s) const
        {
            if (planets[v] == planets[s.v])
                return v - s.v;
            else
                return planets[v] > planets[s.v] ? 1 : -1;
        }
    }
    auto q = redBlackTree!("a < b", true)(cast(S)0);
    while (!q.empty())
    {
        auto v = q.front().v;
        q.removeFront();
        foreach (int to; g[v])
        {
            auto len = weights[cast(tuple)[v, to]];
            if (get(to, planets[v] + len) < planets[to])
            {
                q.removeKey(cast(S)to);
                planets[to] = get(to, planets[v] + len);
                q.insert(cast(S)to);
            }
        }
    }
    writeln(planets[n - 1] == inf ? -1 : planets[n - 1]);
}

void main()
{
    CFBETA142D();
}


import std.stdio, std.string;
import std.conv, std.array;
import std.math, std.algorithm;

int main(string[] args)
{
    auto ret = readln.strip.split(" ").map!(to!int).array;
    auto n = ret[0];
    auto k = to!int(readln.strip);
    auto res = 0;
    auto left = 1, right = n;
    while (left <= right)
    {
        auto mid = (left + right) >> 1;
        writeln("? 1 ", mid);
        stdout.flush;
        auto sum = to!int(readln.strip);
        if (mid - sum < k)
        {
            left = mid + 1;
        }
        else
        {
            right = mid - 1;
            res = mid;
        }
    }
    writeln("! ", res);
    return 0;
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.bigint, std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

void chmin(T)(ref T x, T y) { x = min(x, y); } void chmax(T)(ref T x, T y) { x = max(x, y); }
bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
T lcm(T)(T x, T y) { return x * (y / gcd(x, y)); }
double[] rotate(double[] vec, double rad) { return [cos(rad) * vec[0] - sin(rad) * vec[1], sin(rad) * vec[0] + cos(rad) * vec[1]]; }

long mod = 10^^9 + 7;
//long mod = 998_244_353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }
void modpow(ref long x, long y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(ref long x, long y) { y.modpow(mod - 2); x.modm(y); }

T binarySearch(alias pred, T)(T ok, T ng)
{
	while (abs(ok-ng) > 1)
	{
		auto mid = (ok+ng)/2;
		if (unaryFun!pred(mid)) ok = mid;
		else ng = mid;
	}
	return ok;
}

void main()
{
	auto n = RD!int;
	auto t = RD!int;
	auto k = RD!int;

	bool f(int x)
	{
		writeln("? 1 ", x);
		stdout.flush;
		auto r = RD;
		auto zero = x - r;
		return zero >= k;
	}

	auto ans = binarySearch!(f)(n+1, 0);

	writeln("! ", ans);
	stdout.flush;
	debug readln;
}

import std.stdio, std.conv, std.functional, std.string;
import std.algorithm, std.array, std.container, std.range, std.typecons;
import std.bigint, std.numeric, std.math, std.random;
import core.bitop;

string FMT_F = "%.10f";

static File _f;
void file_io(string fn) { _f = File(fn, "r"); }
static string[] s_rd;
T _RD(T = long)() { while(!s_rd.length) s_rd = readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T _RD(T = long)(File f) { while(!s_rd.length) s_rd = f.readln.chomp.split; string res = s_rd[0]; s_rd.popFront; return res.to!T; }
T[] _RDA(T = long)(T fix = 0) { auto r = readln.chomp.split.to!(T[]); r[] += fix; return r; }
T[] _RDA(T = long)(File f, T fix = 0) { auto r = f.readln.chomp.split.to!(T[]); r[] += fix; return r; }
T RD(T = long)() { if (_f.isOpen) return _RD!T(_f); else return _RD!T; }
T[] RDA(T = long)(T fix = 0) { if (_f.isOpen)  return _RDA!T(_f, fix); else return _RDA!T(fix); }

size_t[] MAKE_IDX(alias less = "a < b", Range)(Range range) { auto idx = new size_t[](range.length); makeIndex!(less)(range, idx); return idx;}
size_t MIN_POS(alias less = "a < b", Range)(Range range) { auto r = minPos!(less)(range); return range.length - r.length; }

void chmin(T)(ref T x, T y) { x = min(x, y); } void chmax(T)(ref T x, T y) { x = max(x, y); }
bool inside(T)(T x, T b, T e) { return x >= b && x < e; }
T lcm(T)(T x, T y) { return x * (y / gcd(x, y)); }
double[] rotate(double[] vec, double rad) { return [cos(rad) * vec[0] - sin(rad) * vec[1], sin(rad) * vec[0] + cos(rad) * vec[1]]; }

long mod = 10^^9 + 7;
//long mod = 998_244_353;
//long mod = 1_000_003;
void moda(ref long x, long y) { x = (x + y) % mod; }
void mods(ref long x, long y) { x = ((x + mod) - (y % mod)) % mod; }
void modm(ref long x, long y) { x = (x * y) % mod; }
void modpow(ref long x, long y) { if (!y) { x = 1; return; } auto t = x; x.modpow(y>>1); x.modm(x); if (y&1) x.modm(t); }
void modd(ref long x, long y) { y.modpow(mod - 2); x.modm(y); }

T binarySearch(alias pred, T)(T ok, T ng)
{
	while (abs(ok-ng) > 1)
	{
		auto mid = (ok+ng)/2;
		if (unaryFun!pred(mid)) ok = mid;
		else ng = mid;
	}
	return ok;
}

void main()
{
	auto n = RD!int;
	auto t = RD!int;
	auto k = RD!int;

	bool f(int x)
	{
		writeln("? 1 ", x);
		stdout.flush;
		auto r = RD;
		auto zero = x - r;
		return zero >= k;
	}

	auto ans = binarySearch!(f)(n+1, 1);

	writeln("! ", ans);
	stdout.flush;
	debug readln;
}