It's that time of the year, Felicity is around the corner and you can see people celebrating all around the Himalayan region. The Himalayan region has n gyms. The i-th gym has gi Pokemon in it. There are m distinct Pokemon types in the Himalayan region numbered from 1 to m. There is a special evolution camp set up in the fest which claims to evolve any Pokemon. The type of a Pokemon could change after evolving, subject to the constraint that if two Pokemon have the same type before evolving, they will have the same type after evolving. Also, if two Pokemon have different types before evolving, they will have different types after evolving. It is also possible that a Pokemon has the same type before and after evolving. Formally, an evolution plan is a permutation f of {1, 2, ..., m}, such that f(x) = y means that a Pokemon of type x evolves into a Pokemon of type y.The gym leaders are intrigued by the special evolution camp and all of them plan to evolve their Pokemons. The protocol of the mountain states that in each gym, for every type of Pokemon, the number of Pokemon of that type before evolving any Pokemon should be equal the number of Pokemon of that type after evolving all the Pokemons according to the evolution plan. They now want to find out how many distinct evolution plans exist which satisfy the protocol.Two evolution plans f1 and f2 are distinct, if they have at least one Pokemon type evolving into a different Pokemon type in the two plans, i. e. there exists an i such that f1(i) ≠ f2(i).Your task is to find how many distinct evolution plans are possible such that if all Pokemon in all the gyms are evolved, the number of Pokemon of each type in each of the gyms remains the same. As the answer can be large, output it modulo 109 + 7.

The first line contains two integers n and m (1 ≤ n ≤ 105, 1 ≤ m ≤ 106) — the number of gyms and the number of Pokemon types. The next n lines contain the description of Pokemons in the gyms. The i-th of these lines begins with the integer gi (1 ≤ gi ≤ 105) — the number of Pokemon in the i-th gym. After that gi integers follow, denoting types of the Pokemons in the i-th gym. Each of these integers is between 1 and m. The total number of Pokemons (the sum of all gi) does not exceed 5·105.

Output the number of valid evolution plans modulo 109 + 7.

NoteIn the first case, the only possible evolution plan is: In the second case, any permutation of (1,  2,  3) is valid.In the third case, there are two possible plans:  In the fourth case, the only possible evolution plan is:

module main;
import std.bigint,std.container,std.array,std.algorithm,std.conv,
	std.functional,std.math,std.numeric,std.string,std.range,std.complex,
	std.typecons,std.regex,std.random,std.uni,std.traits,std.variant,
	std.stdio,std.bitmanip;
import core.stdc.stdio : freopen;
alias BitArray bitset;
alias RedBlackTree Rbt;
alias redBlackTree rbt;
alias BigInt big;
alias pair!(int,int) pii;
alias pair!(long,long) pll;
alias BoyerMooreFinder strfind;
alias make_pair mp;
alias binary_search bins;
alias orient_square orsq;
immutable int mod=10^^9+7;
pure nothrow
{
	T lcm (T)(auto ref T a,auto ref T b)
	{
		return a/gcd(a,b)*b;
	}
	X binpow(X,Y)(X base,Y exp)
		if(is(typeof(exp&1)))
	{
		if(exp<0)return X(0);
		X res=X(1);
		while(exp>0)
		{
			if(exp&1)res*=base;
			base*=base;
			exp>>=1;
		}
		return res;
	}
	auto binpow(X,Y,Z)(X base,Y exp,in Z mm)
		if(is(typeof(exp&1)))
	{
		if(mm==0) return binpow(base,exp);
		if(exp<0)return X(0);
		auto res=X(1)%mm;
		while(exp>0)
		{
			if(exp&1)res=(res*base)%mm;
			base*=base;
			base%=mm;
			exp>>=1;
		}
		return res;
	}
	@property X sqr(X)(in X a_) {return a_*a_;}
	@property X cub(X)(in X a_) {return a_*a_*a_;}
	size_t lowb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (!(a[l]<g))?l:r;
	}
	size_t upb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(g<a[m])r=m;
			else l=m;
		}
		return (g<a[l])?l:r;
	}
	size_t binf(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (g==a[l])?l:a.length;
	}
	bool binary_search(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		return binf(a,g)!=a.length;
	}
	V foldr(R,V,T)(R range,T arg,V nach)
		if(isFunction!T && isInputRange!R && is(typeof(arg(nach,R.front))==V))
	{
		for(;!range.empty;range.popFront()) nach=arg(nach,range.front);
		return nach;
	}
	size_t countr(R,T)(R range,T fun)
		if(isFunction!T && isInputRange!R && is(typeof(fun(R.front))==bool))
	{
		size_t nach;
		for(;!range.empty;range.popFront()) nach+=fun(range.front);
		return nach;
	}
	T orient_square(T)(pair!(T,T)[] figure...)
	{
		auto n=figure.front,t=figure.front;
		figure.popFront();
		T ans=0;
		for(;!figure.empty;figure.popFront())
		{
			ans+=(figure.front.fi-t.fi)*(figure.front.se+t.se);
			t=figure.front;
		}
		return ans+(n.fi-t.fi)*(n.se+t.se);
	}
	real square(T)(pair!(T,T)[] figure...)
		if(is(typeof(figure.front*figure.front)==T))
	{
		return abs(orient_square(figure))/2.000000000000000;
	}
}
void putarr(X)(in X a,in char ch=' '){foreach(const ref i;a)write(i,ch);}
void putarr(X)(in X a,in size_t n,in size_t m)
{
	foreach(i;0..n)
	{
		foreach(j;0..m)write(a[i][j],' ');
		writeln;
	}
}
bool getarr(X)(X a,in size_t n)
{bool b=1; foreach(ref i;a[0..n])b=input(&i);return b;}
bool input(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length), ptrs)==ptrs.length;}
bool read(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length)~'\n', ptrs)==ptrs.length;}
struct pair(X,Y)
{
	X first;
	Y second;
	alias first fi;
	alias second se;
	this(X a_,Y b_){
		fi=a_;
		se=b_;
	}
	this(this){fi=fi;se=se;}
	this(A,B)(auto ref pair!(A,B) p) if(is(A:X) && is(B:Y))
	{
		fi=p.fi;
		se=p.se;
	}
	int opCmp(A,B)(in pair!(A,B) s_) const
		if(is(typeof(s_.fi<fi)==bool) && is(typeof(s_.se<se)==bool))
	{
		int cmp=0-(fi<s_.fi)+(fi>s_.fi);
		if(cmp!=0)return cmp;
		else return (0-(se<s_.se)+(se>s_.se));
	}
};
pair!(X,Y) make_pair(X,Y)(in X x_,in Y y_)
{
	pair!(X,Y) pp;
	pp.fi=x_;
	pp.se=y_;
	return pp;
}
nothrow void inf(in char* name) {freopen(name,"r",core.stdc.stdio.stdin);}
nothrow void ouf(in char* name) {freopen(name,"w",core.stdc.stdio.stdout);}
@property auto arread(T)(){return readln.split.map!(to!(T)).array;}
//split strip isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold schwartzSort multiSort partialSort heapify join filter countUntil
//---------------------------------------------------------------program beginning-----------------------------------------------------------------

void main()
{
	int n,m;
	loop:while(read(&n,&m))
	{
		auto g=new int[][m+1];
		foreach(i;1..n+1)
		{
			int k;
			input(&k);
			foreach(j;0..k)
			{
				int f;
				input(&f);
				g[f]~=i;
			}
		}
		int[int[]] q;
		foreach(i;g[1..$])
		{
			q[i.idup]++;
		}
		auto fact=(1L~iota(1L,5L*(10^^6)).array).cumulativeFold!"(a*b)%1000000007"(1L).array;
		long ans=1;
		foreach(i;q.byValue)
		{
			ans=(ans*fact[i])%mod;
		}
		/*long ans=1,t=1;
		sort(g[1..$]);
		debug foreach(i;g)writeln(i);
		foreach(i;2..m+1)
		{
			if(g[i]==g[i-1])
			{
				ans=(ans*(++t))%mod;
			}
			else t=1;
		}*/
		writeln(ans);
	}
}

module main;
import std.bigint,std.container,std.array,std.algorithm,std.conv,
	std.functional,std.math,std.numeric,std.string,std.range,std.complex,
	std.typecons,std.regex,std.random,std.uni,std.traits,std.variant,
	std.stdio,std.bitmanip;
import core.stdc.stdio : freopen;
alias BitArray bitset;
alias RedBlackTree Rbt;
alias redBlackTree rbt;
alias BigInt big;
alias pair!(int,int) pii;
alias pair!(long,long) pll;
alias BoyerMooreFinder strfind;
alias make_pair mp;
alias binary_search bins;
alias orient_square orsq;
immutable int mod=10^^9+7;
pure nothrow
{
	T lcm (T)(auto ref T a,auto ref T b)
	{
		return a/gcd(a,b)*b;
	}
	X binpow(X,Y)(X base,Y exp)
		if(is(typeof(exp&1)))
	{
		if(exp<0)return X(0);
		X res=X(1);
		while(exp>0)
		{
			if(exp&1)res*=base;
			base*=base;
			exp>>=1;
		}
		return res;
	}
	auto binpow(X,Y,Z)(X base,Y exp,in Z mm)
		if(is(typeof(exp&1)))
	{
		if(mm==0) return binpow(base,exp);
		if(exp<0)return X(0);
		auto res=X(1)%mm;
		while(exp>0)
		{
			if(exp&1)res=(res*base)%mm;
			base*=base;
			base%=mm;
			exp>>=1;
		}
		return res;
	}
	@property X sqr(X)(in X a_) {return a_*a_;}
	@property X cub(X)(in X a_) {return a_*a_*a_;}
	size_t lowb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (!(a[l]<g))?l:r;
	}
	size_t upb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(g<a[m])r=m;
			else l=m;
		}
		return (g<a[l])?l:r;
	}
	size_t binf(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (g==a[l])?l:a.length;
	}
	bool binary_search(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		return binf(a,g)!=a.length;
	}
	V foldr(R,V,T)(R range,T arg,V nach)
		if(isFunction!T && isInputRange!R && is(typeof(arg(nach,R.front))==V))
	{
		for(;!range.empty;range.popFront()) nach=arg(nach,range.front);
		return nach;
	}
	size_t countr(R,T)(R range,T fun)
		if(isFunction!T && isInputRange!R && is(typeof(fun(R.front))==bool))
	{
		size_t nach;
		for(;!range.empty;range.popFront()) nach+=fun(range.front);
		return nach;
	}
	T orient_square(T)(pair!(T,T)[] figure...)
	{
		auto n=figure.front,t=figure.front;
		figure.popFront();
		T ans=0;
		for(;!figure.empty;figure.popFront())
		{
			ans+=(figure.front.fi-t.fi)*(figure.front.se+t.se);
			t=figure.front;
		}
		return ans+(n.fi-t.fi)*(n.se+t.se);
	}
	real square(T)(pair!(T,T)[] figure...)
		if(is(typeof(figure.front*figure.front)==T))
	{
		return abs(orient_square(figure))/2.000000000000000;
	}
}
void putarr(X)(in X a,in char ch=' '){foreach(const ref i;a)write(i,ch);}
void putarr(X)(in X a,in size_t n,in size_t m)
{
	foreach(i;0..n)
	{
		foreach(j;0..m)write(a[i][j],' ');
		writeln;
	}
}
bool getarr(X)(X a,in size_t n)
{bool b=1; foreach(ref i;a[0..n])b=input(&i);return b;}
bool input(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length), ptrs)==ptrs.length;}
bool read(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length)~'\n', ptrs)==ptrs.length;}
struct pair(X,Y)
{
	X first;
	Y second;
	alias first fi;
	alias second se;
	this(X a_,Y b_){
		fi=a_;
		se=b_;
	}
	this(this){fi=fi;se=se;}
	this(A,B)(auto ref pair!(A,B) p) if(is(A:X) && is(B:Y))
	{
		fi=p.fi;
		se=p.se;
	}
	int opCmp(A,B)(in pair!(A,B) s_) const
		if(is(typeof(s_.fi<fi)==bool) && is(typeof(s_.se<se)==bool))
	{
		int cmp=0-(fi<s_.fi)+(fi>s_.fi);
		if(cmp!=0)return cmp;
		else return (0-(se<s_.se)+(se>s_.se));
	}
};
pair!(X,Y) make_pair(X,Y)(in X x_,in Y y_)
{
	pair!(X,Y) pp;
	pp.fi=x_;
	pp.se=y_;
	return pp;
}
nothrow void inf(in char* name) {freopen(name,"r",core.stdc.stdio.stdin);}
nothrow void ouf(in char* name) {freopen(name,"w",core.stdc.stdio.stdout);}
@property auto arread(T)(){return readln.split.map!(to!(T)).array;}
//split strip isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold schwartzSort multiSort partialSort heapify join filter countUntil
//---------------------------------------------------------------program beginning-----------------------------------------------------------------

void main()
{
	int n,m;
	loop:while(read(&n,&m))
	{
		auto g=new int[][m+1];
		foreach(i;1..n+1)
		{
			int k;
			input(&k);
			foreach(j;0..k)
			{
				int f;
				input(&f);
				g[f]~=i;
			}
		}
		int[int[]] q;
		foreach(i;g[1..$])
		{
			q[i.idup]++;
		}
		auto fact=(1L~iota(1L,(10^^6)).array).cumulativeFold!"(a*b)%1000000007"(1L).array;
		long ans=1;
		foreach(i;q.byValue)
		{
			ans=(ans*fact[i])%mod;
		}
		/*long ans=1,t=1;
		sort(g[1..$]);
		debug foreach(i;g)writeln(i);
		foreach(i;2..m+1)
		{
			if(g[i]==g[i-1])
			{
				ans=(ans*(++t))%mod;
			}
			else t=1;
		}*/
		writeln(ans);
	}
}

module main;
import std.bigint,std.container,std.array,std.algorithm,std.conv,
	std.functional,std.math,std.numeric,std.string,std.range,std.complex,
	std.typecons,std.regex,std.random,std.uni,std.traits,std.variant,
	std.stdio,std.bitmanip;
import core.stdc.stdio : freopen;
alias BitArray bitset;
alias RedBlackTree Rbt;
alias redBlackTree rbt;
alias BigInt big;
alias pair!(int,int) pii;
alias pair!(long,long) pll;
alias BoyerMooreFinder strfind;
alias make_pair mp;
alias binary_search bins;
alias orient_square orsq;
immutable int mod=10^^9+7;
pure nothrow
{
	T lcm (T)(auto ref T a,auto ref T b)
	{
		return a/gcd(a,b)*b;
	}
	X binpow(X,Y)(X base,Y exp)
		if(is(typeof(exp&1)))
	{
		if(exp<0)return X(0);
		X res=X(1);
		while(exp>0)
		{
			if(exp&1)res*=base;
			base*=base;
			exp>>=1;
		}
		return res;
	}
	auto binpow(X,Y,Z)(X base,Y exp,in Z mm)
		if(is(typeof(exp&1)))
	{
		if(mm==0) return binpow(base,exp);
		if(exp<0)return X(0);
		auto res=X(1)%mm;
		while(exp>0)
		{
			if(exp&1)res=(res*base)%mm;
			base*=base;
			base%=mm;
			exp>>=1;
		}
		return res;
	}
	@property X sqr(X)(in X a_) {return a_*a_;}
	@property X cub(X)(in X a_) {return a_*a_*a_;}
	size_t lowb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (!(a[l]<g))?l:r;
	}
	size_t upb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(g<a[m])r=m;
			else l=m;
		}
		return (g<a[l])?l:r;
	}
	size_t binf(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (g==a[l])?l:a.length;
	}
	bool binary_search(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		return binf(a,g)!=a.length;
	}
	V foldr(R,V,T)(R range,T arg,V nach)
		if(isFunction!T && isInputRange!R && is(typeof(arg(nach,R.front))==V))
	{
		for(;!range.empty;range.popFront()) nach=arg(nach,range.front);
		return nach;
	}
	size_t countr(R,T)(R range,T fun)
		if(isFunction!T && isInputRange!R && is(typeof(fun(R.front))==bool))
	{
		size_t nach;
		for(;!range.empty;range.popFront()) nach+=fun(range.front);
		return nach;
	}
	T orient_square(T)(pair!(T,T)[] figure...)
	{
		auto n=figure.front,t=figure.front;
		figure.popFront();
		T ans=0;
		for(;!figure.empty;figure.popFront())
		{
			ans+=(figure.front.fi-t.fi)*(figure.front.se+t.se);
			t=figure.front;
		}
		return ans+(n.fi-t.fi)*(n.se+t.se);
	}
	real square(T)(pair!(T,T)[] figure...)
		if(is(typeof(figure.front*figure.front)==T))
	{
		return abs(orient_square(figure))/2.000000000000000;
	}
}
void putarr(X)(in X a,in char ch=' '){foreach(const ref i;a)write(i,ch);}
void putarr(X)(in X a,in size_t n,in size_t m)
{
	foreach(i;0..n)
	{
		foreach(j;0..m)write(a[i][j],' ');
		writeln;
	}
}
bool getarr(X)(X a,in size_t n)
{bool b=1; foreach(ref i;a[0..n])b=input(&i);return b;}
bool input(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length), ptrs)==ptrs.length;}
bool read(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length)~'\n', ptrs)==ptrs.length;}
struct pair(X,Y)
{
	X first;
	Y second;
	alias first fi;
	alias second se;
	this(X a_,Y b_){
		fi=a_;
		se=b_;
	}
	this(this){fi=fi;se=se;}
	this(A,B)(auto ref pair!(A,B) p) if(is(A:X) && is(B:Y))
	{
		fi=p.fi;
		se=p.se;
	}
	int opCmp(A,B)(in pair!(A,B) s_) const
		if(is(typeof(s_.fi<fi)==bool) && is(typeof(s_.se<se)==bool))
	{
		int cmp=0-(fi<s_.fi)+(fi>s_.fi);
		if(cmp!=0)return cmp;
		else return (0-(se<s_.se)+(se>s_.se));
	}
};
pair!(X,Y) make_pair(X,Y)(in X x_,in Y y_)
{
	pair!(X,Y) pp;
	pp.fi=x_;
	pp.se=y_;
	return pp;
}
nothrow void inf(in char* name) {freopen(name,"r",core.stdc.stdio.stdin);}
nothrow void ouf(in char* name) {freopen(name,"w",core.stdc.stdio.stdout);}
@property auto arread(T)(){return readln.split.map!(to!(T)).array;}
//split strip isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold schwartzSort multiSort partialSort heapify join filter countUntil
//---------------------------------------------------------------program beginning-----------------------------------------------------------------

void main()
{
	int n,m;
	loop:while(read(&n,&m))
	{
		auto g=new int[][m+1];
		foreach(i;1..n+1)
		{
			int k;
			input(&k);
			foreach(j;0..k)
			{
				int f;
				input(&f);
				g[f]~=i;
			}
		}
		/*int[int[]] q;
		foreach(i;g)
		{
			if(i.length)q[i.idup]++;
		}
		auto fact=(1L~iota(1L,5L*(10^^5)+1).array).cumulativeFold!"(a*b)%1000000007"(1L).array;
		long ans=1;
		foreach(i;q.byValue)
		{
			ans=(ans*fact[i])%mod;
		}*/
		long ans=1,t=1;
		sort(g[1..$]);
		debug foreach(i;g)writeln(i);
		foreach(i;2..m+1)
		{
			if(g[i]==g[i-1])
			{
				ans=(ans*(++t))%mod;
			}
			else t=1;
		}
		writeln(ans);
	}
}

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.typecons;

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

    auto idx = new int[] (m+1);
    int nxtid = 1;
    foreach (_; 0 .. n) {
        auto nrs = readln.chomp.split.map!(to!int).dropOne.array;

        int[int] cnt;

        foreach (e; nrs) { cnt[e] += 1; }

        int[][int] groups;
        foreach (p; cnt.byKeyValue) {
            groups[p.value] ~= p.key;
        }

        debug { groups.writeln; }

        foreach (arr; groups.values) {
            arr.schwartzSort!(x => idx[x]);

            foreach (p, n; lockstep(arr, arr.dropOne)) {
                bool inc = idx[p] != idx[n];

                idx[p] = nxtid;

                if (inc) { nxtid += 1; }
            }

            idx[arr.back] = nxtid;

            ++nxtid;
        }

        debug { idx.dropOne.writeln; }
    }

    debug { idx.writeln; }

    auto grouped = idx.dropOne.sort.group.map!(t => t[1]);

    debug { grouped.writeln; }

    immutable int MD = 10 ^^ 9 + 7;

    auto fac = new int[] (m+1);
    fac[0] = 1;
    foreach (i; 1 .. m+1) { fac[i] = fac[i-1].to!long * i % MD; }

    auto ans = grouped.map!(x => fac[x])
        .fold!((x, y) => (x.to!long * y % MD).to!int)(1);

    ans.writeln;
}

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

immutable int mod = 10 ^^ 9 + 7;

void main ()
{
	int n;
	int m;
	while (readf (" %s %s", &n, &m) > 0)
	{
		readln;
		auto hash = new ulong [m];
		foreach (i; 0..n)
		{
			int [int] num;
			foreach (type; readln.split.drop (1).map !(to !(int)))
			{
				num[type] += 1;
			}
			alias Pair = Tuple !(int, q{num}, int, q{type});
			Pair [] a;
			a.reserve (num.length);
			foreach (key, value; num)
			{
				a ~= Pair (value, key);
			}
			sort (a);
			foreach (g; a.chunkBy !(p => p.num))
			{
				auto v = uniform !(ulong) ();
				foreach (type; g[1].map !(x => x.type))
				{
					hash[type - 1] ^= v;
				}
			}
		}
		debug {writeln (hash);}

		long res = 1;
		sort (hash);
		foreach (num; hash.group)
		{
			foreach (i; 0..num[1])
			{
				res = (res * 1L * (i + 1)) % mod;
			}
		}
		writeln (res);
	}
}

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

immutable long mod = 10^^9 + 7;

void main(){
    int N, M;
    readVars(N, M);

    auto types = new int[][M];

    foreach(i ; 0 .. N){
        auto line = readln.split.to!(int[]);

        foreach(t ; line[1 .. $]){
            types[t - 1] ~= i;
        }
    }

    foreach(i ; 0 .. types.length.to!int){
        sort(types[i]);
    }

    sort(types);

    long ans = 1, cnt = 1;

    foreach(i ; 0 .. types.length.to!int - 1){
        if (types[i] == types[i + 1]){
            cnt++;
            ans = (ans * cnt) % mod;
        } else {
            cnt = 1;
        }
    }

    writeln(ans);
}

void readVars(T...)(auto ref T args){
    auto line = readln.split;
    foreach(ref arg ; args){
        arg = line.front.to!(typeof(arg));
        line.popFront;
    }
    if(!line.empty){
        throw new Exception("args num < input num");
    }
}

module main;
import std.bigint,std.container,std.array,std.algorithm,std.conv,
	std.functional,std.math,std.numeric,std.string,std.range,std.complex,
	std.typecons,std.regex,std.random,std.uni,std.traits,std.variant,
	std.stdio,std.bitmanip;
import core.stdc.stdio : freopen;
alias BitArray bitset;
alias RedBlackTree Rbt;
alias redBlackTree rbt;
alias BigInt big;
alias pair!(int,int) pii;
alias pair!(long,long) pll;
alias BoyerMooreFinder strfind;
alias make_pair mp;
alias binary_search bins;
alias orient_square orsq;
immutable int mod=10^^9+7;
pure nothrow
{
	T lcm (T)(auto ref T a,auto ref T b)
	{
		return a/gcd(a,b)*b;
	}
	X binpow(X,Y)(X base,Y exp)
		if(is(typeof(exp&1)))
	{
		if(exp<0)return X(0);
		X res=X(1);
		while(exp>0)
		{
			if(exp&1)res*=base;
			base*=base;
			exp>>=1;
		}
		return res;
	}
	auto binpow(X,Y,Z)(X base,Y exp,in Z mm)
		if(is(typeof(exp&1)))
	{
		if(mm==0) return binpow(base,exp);
		if(exp<0)return X(0);
		auto res=X(1)%mm;
		while(exp>0)
		{
			if(exp&1)res=(res*base)%mm;
			base*=base;
			base%=mm;
			exp>>=1;
		}
		return res;
	}
	@property X sqr(X)(in X a_) {return a_*a_;}
	@property X cub(X)(in X a_) {return a_*a_*a_;}
	size_t lowb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (!(a[l]<g))?l:r;
	}
	size_t upb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(g<a[m])r=m;
			else l=m;
		}
		return (g<a[l])?l:r;
	}
	size_t binf(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (g==a[l])?l:a.length;
	}
	bool binary_search(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		return binf(a,g)!=a.length;
	}
	V foldr(R,V,T)(R range,T arg,V nach)
		if(isFunction!T && isInputRange!R && is(typeof(arg(nach,R.front))==V))
	{
		for(;!range.empty;range.popFront()) nach=arg(nach,range.front);
		return nach;
	}
	size_t countr(R,T)(R range,T fun)
		if(isFunction!T && isInputRange!R && is(typeof(fun(R.front))==bool))
	{
		size_t nach;
		for(;!range.empty;range.popFront()) nach+=fun(range.front);
		return nach;
	}
	T orient_square(T)(pair!(T,T)[] figure...)
	{
		auto n=figure.front,t=figure.front;
		figure.popFront();
		T ans=0;
		for(;!figure.empty;figure.popFront())
		{
			ans+=(figure.front.fi-t.fi)*(figure.front.se+t.se);
			t=figure.front;
		}
		return ans+(n.fi-t.fi)*(n.se+t.se);
	}
	real square(T)(pair!(T,T)[] figure...)
		if(is(typeof(figure.front*figure.front)==T))
	{
		return abs(orient_square(figure))/2.000000000000000;
	}
}
void putarr(X)(in X a,in char ch=' '){foreach(const ref i;a)write(i,ch);}
void putarr(X)(in X a,in size_t n,in size_t m)
{
	foreach(i;0..n)
	{
		foreach(j;0..m)write(a[i][j],' ');
		writeln;
	}
}
bool getarr(X)(X a,in size_t n)
{bool b=1; foreach(ref i;a[0..n])b=input(&i);return b;}
bool input(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length), ptrs)==ptrs.length;}
bool read(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length)~'\n', ptrs)==ptrs.length;}
struct pair(X,Y)
{
	X first;
	Y second;
	alias first fi;
	alias second se;
	this(X a_,Y b_){
		fi=a_;
		se=b_;
	}
	this(this){fi=fi;se=se;}
	this(A,B)(auto ref pair!(A,B) p) if(is(A:X) && is(B:Y))
	{
		fi=p.fi;
		se=p.se;
	}
	int opCmp(A,B)(in pair!(A,B) s_) const
		if(is(typeof(s_.fi<fi)==bool) && is(typeof(s_.se<se)==bool))
	{
		int cmp=0-(fi<s_.fi)+(fi>s_.fi);
		if(cmp!=0)return cmp;
		else return (0-(se<s_.se)+(se>s_.se));
	}
};
pair!(X,Y) make_pair(X,Y)(in X x_,in Y y_)
{
	pair!(X,Y) pp;
	pp.fi=x_;
	pp.se=y_;
	return pp;
}
nothrow void inf(in char* name) {freopen(name,"r",core.stdc.stdio.stdin);}
nothrow void ouf(in char* name) {freopen(name,"w",core.stdc.stdio.stdout);}
@property auto arread(T)(){return readln.split.map!(to!(T)).array;}
//split strip isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold schwartzSort multiSort partialSort heapify join filter countUntil
//---------------------------------------------------------------program beginning-----------------------------------------------------------------

void main()
{
	int n,m;
	loop:while(read(&n,&m))
	{
		auto g=new int[][m+1];
		foreach(i;1..n+1)
		{
			int k;
			input(&k);
			foreach(j;0..k)
			{
				int f;
				input(&f);
				g[f]~=i;
			}
		}
		int[int[]] q;
		foreach(i;g[1..$])
		{
			q[i.idup]++;
		}
		auto fact=(1L~iota(1L,5L*(10^^5)+1).array).cumulativeFold!"(a*b)%1000000007"(1L).array;
		long ans=1;
		foreach(i;q.byValue)
		{
			ans=(ans*fact[i])%mod;
		}
		/*long ans=1,t=1;
		sort(g[1..$]);
		debug foreach(i;g)writeln(i);
		foreach(i;2..m+1)
		{
			if(g[i]==g[i-1])
			{
				ans=(ans*(++t))%mod;
			}
			else t=1;
		}*/
		writeln(ans);
	}
}

module main;
import std.bigint,std.container,std.array,std.algorithm,std.conv,
	std.functional,std.math,std.numeric,std.string,std.range,std.complex,
	std.typecons,std.regex,std.random,std.uni,std.traits,std.variant,
	std.stdio,std.bitmanip;
import core.stdc.stdio : freopen;
alias BitArray bitset;
alias RedBlackTree Rbt;
alias redBlackTree rbt;
alias BigInt big;
alias pair!(int,int) pii;
alias pair!(long,long) pll;
alias BoyerMooreFinder strfind;
alias make_pair mp;
alias binary_search bins;
alias orient_square orsq;
immutable int mod=1000000007;
pure nothrow
{
	T lcm (T)(auto ref T a,auto ref T b)
	{
		return a/gcd(a,b)*b;
	}
	X binpow(X,Y)(X base,Y exp)
		if(is(typeof(exp&1)))
	{
		if(exp<0)return X(0);
		X res=X(1);
		while(exp>0)
		{
			if(exp&1)res*=base;
			base*=base;
			exp>>=1;
		}
		return res;
	}
	auto binpow(X,Y,Z)(X base,Y exp,in Z mm)
		if(is(typeof(exp&1)))
	{
		if(mm==0) return binpow(base,exp);
		if(exp<0)return X(0);
		auto res=X(1)%mm;
		while(exp>0)
		{
			if(exp&1)res=(res*base)%mm;
			base*=base;
			base%=mm;
			exp>>=1;
		}
		return res;
	}
	@property X sqr(X)(in X a_) {return a_*a_;}
	@property X cub(X)(in X a_) {return a_*a_*a_;}
	size_t lowb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (!(a[l]<g))?l:r;
	}
	size_t upb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(g<a[m])r=m;
			else l=m;
		}
		return (g<a[l])?l:r;
	}
	size_t binf(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (g==a[l])?l:a.length;
	}
	bool binary_search(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		return binf(a,g)!=a.length;
	}
	V foldr(R,V,T)(R range,T arg,V nach)
		if(isFunction!T && isInputRange!R && is(typeof(arg(nach,R.front))==V))
	{
		for(;!range.empty;range.popFront()) nach=arg(nach,range.front);
		return nach;
	}
	size_t countr(R,T)(R range,T fun)
		if(isFunction!T && isInputRange!R && is(typeof(fun(R.front))==bool))
	{
		size_t nach;
		for(;!range.empty;range.popFront()) nach+=fun(range.front);
		return nach;
	}
	T orient_square(T)(pair!(T,T)[] figure...)
	{
		auto n=figure.front,t=figure.front;
		figure.popFront();
		T ans=0;
		for(;!figure.empty;figure.popFront())
		{
			ans+=(figure.front.fi-t.fi)*(figure.front.se+t.se);
			t=figure.front;
		}
		return ans+(n.fi-t.fi)*(n.se+t.se);
	}
	real square(T)(pair!(T,T)[] figure...)
		if(is(typeof(figure.front*figure.front)==T))
	{
		return abs(orient_square(figure))/2.000000000000000;
	}
}
void putarr(X)(in X a,in char ch=' '){foreach(const ref i;a)write(i,ch);}
void putarr(X)(in X a,in size_t n,in size_t m)
{
	foreach(i;0..n)
	{
		foreach(j;0..m)write(a[i][j],' ');
		writeln;
	}
}
bool getarr(X)(X a,in size_t n)
{bool b=1; foreach(ref i;a[0..n])b=input(&i);return b;}
bool input(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length), ptrs)==ptrs.length;}
bool read(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length)~'\n', ptrs)==ptrs.length;}
struct pair(X,Y)
{
	X first;
	Y second;
	alias first fi;
	alias second se;
	this(X a_,Y b_){
		fi=a_;
		se=b_;
	}
	this(this){fi=fi;se=se;}
	this(A,B)(auto ref pair!(A,B) p) if(is(A:X) && is(B:Y))
	{
		fi=p.fi;
		se=p.se;
	}
	int opCmp(A,B)(in pair!(A,B) s_) const
		if(is(typeof(s_.fi<fi)==bool) && is(typeof(s_.se<se)==bool))
	{
		int cmp=0-(fi<s_.fi)+(fi>s_.fi);
		if(cmp!=0)return cmp;
		else return (0-(se<s_.se)+(se>s_.se));
	}
};
pair!(X,Y) make_pair(X,Y)(in X x_,in Y y_)
{
	pair!(X,Y) pp;
	pp.fi=x_;
	pp.se=y_;
	return pp;
}
nothrow void inf(in char* name) {freopen(name,"r",core.stdc.stdio.stdin);}
nothrow void ouf(in char* name) {freopen(name,"w",core.stdc.stdio.stdout);}
@property auto arread(T)(){return readln.split.map!(to!(T)).array;}
//split strip isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold schwartzSort multiSort partialSort heapify join filter countUntil
//---------------------------------------------------------------program beginning-----------------------------------------------------------------

void main()
{
	int n,m;
	loop:while(read(&n,&m))
	{
		auto g=new int[][m+1];
		foreach(i;0..n)
		{
			int k;
			input(&k);
			foreach(j;0..k)
			{
				int f;
				input(&f);
				g[f]~=i;
			}
		}
		int[int[]] q;
		foreach(i;g)
		{
			if(i.length)q[i.idup]++;
		}
		auto fact=1L~iota(1L,5L*(10^^5)+1).cumulativeFold!"(a*b)%1000000007"(1L).array;
		long ans=1;
		foreach(i;q.byValue)
		{
			ans=(ans*fact[i])%mod;
		}
		writeln(ans);
	}
}

module main;
import std.bigint,std.container,std.array,std.algorithm,std.conv,
	std.functional,std.math,std.numeric,std.string,std.range,std.complex,
	std.typecons,std.regex,std.random,std.uni,std.traits,std.variant,
	std.stdio,std.bitmanip;
import core.stdc.stdio : freopen;
alias BitArray bitset;
alias RedBlackTree Rbt;
alias redBlackTree rbt;
alias BigInt big;
alias pair!(int,int) pii;
alias pair!(long,long) pll;
alias BoyerMooreFinder strfind;
alias make_pair mp;
alias binary_search bins;
alias orient_square orsq;
immutable int mod=1000000007;
pure nothrow
{
	T lcm (T)(auto ref T a,auto ref T b)
	{
		return a/gcd(a,b)*b;
	}
	X binpow(X,Y)(X base,Y exp)
		if(is(typeof(exp&1)))
	{
		if(exp<0)return X(0);
		X res=X(1);
		while(exp>0)
		{
			if(exp&1)res*=base;
			base*=base;
			exp>>=1;
		}
		return res;
	}
	auto binpow(X,Y,Z)(X base,Y exp,in Z mm)
		if(is(typeof(exp&1)))
	{
		if(mm==0) return binpow(base,exp);
		if(exp<0)return X(0);
		auto res=X(1)%mm;
		while(exp>0)
		{
			if(exp&1)res=(res*base)%mm;
			base*=base;
			base%=mm;
			exp>>=1;
		}
		return res;
	}
	@property X sqr(X)(in X a_) {return a_*a_;}
	@property X cub(X)(in X a_) {return a_*a_*a_;}
	size_t lowb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (!(a[l]<g))?l:r;
	}
	size_t upb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(g<a[m])r=m;
			else l=m;
		}
		return (g<a[l])?l:r;
	}
	size_t binf(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (g==a[l])?l:a.length;
	}
	bool binary_search(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		return binf(a,g)!=a.length;
	}
	V foldr(R,V,T)(R range,T arg,V nach)
		if(isFunction!T && isInputRange!R && is(typeof(arg(nach,R.front))==V))
	{
		for(;!range.empty;range.popFront()) nach=arg(nach,range.front);
		return nach;
	}
	size_t countr(R,T)(R range,T fun)
		if(isFunction!T && isInputRange!R && is(typeof(fun(R.front))==bool))
	{
		size_t nach;
		for(;!range.empty;range.popFront()) nach+=fun(range.front);
		return nach;
	}
	T orient_square(T)(pair!(T,T)[] figure...)
	{
		auto n=figure.front,t=figure.front;
		figure.popFront();
		T ans=0;
		for(;!figure.empty;figure.popFront())
		{
			ans+=(figure.front.fi-t.fi)*(figure.front.se+t.se);
			t=figure.front;
		}
		return ans+(n.fi-t.fi)*(n.se+t.se);
	}
	real square(T)(pair!(T,T)[] figure...)
		if(is(typeof(figure.front*figure.front)==T))
	{
		return abs(orient_square(figure))/2.000000000000000;
	}
}
void putarr(X)(in X a,in char ch=' '){foreach(const ref i;a)write(i,ch);}
void putarr(X)(in X a,in size_t n,in size_t m)
{
	foreach(i;0..n)
	{
		foreach(j;0..m)write(a[i][j],' ');
		writeln;
	}
}
bool getarr(X)(X a,in size_t n)
{bool b=1; foreach(ref i;a[0..n])b=input(&i);return b;}
bool input(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length), ptrs)==ptrs.length;}
bool read(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length)~'\n', ptrs)==ptrs.length;}
struct pair(X,Y)
{
	X first;
	Y second;
	alias first fi;
	alias second se;
	this(X a_,Y b_){
		fi=a_;
		se=b_;
	}
	this(this){fi=fi;se=se;}
	this(A,B)(auto ref pair!(A,B) p) if(is(A:X) && is(B:Y))
	{
		fi=p.fi;
		se=p.se;
	}
	int opCmp(A,B)(in pair!(A,B) s_) const
		if(is(typeof(s_.fi<fi)==bool) && is(typeof(s_.se<se)==bool))
	{
		int cmp=0-(fi<s_.fi)+(fi>s_.fi);
		if(cmp!=0)return cmp;
		else return (0-(se<s_.se)+(se>s_.se));
	}
};
pair!(X,Y) make_pair(X,Y)(in X x_,in Y y_)
{
	pair!(X,Y) pp;
	pp.fi=x_;
	pp.se=y_;
	return pp;
}
nothrow void inf(in char* name) {freopen(name,"r",core.stdc.stdio.stdin);}
nothrow void ouf(in char* name) {freopen(name,"w",core.stdc.stdio.stdout);}
@property auto arread(T)(){return readln.split.map!(to!(T)).array;}
//split strip isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold schwartzSort multiSort partialSort heapify join filter countUntil
//---------------------------------------------------------------program beginning-----------------------------------------------------------------

void main()
{
	int n,m;
	loop:while(read(&n,&m))
	{
		auto g=new int[][m+1];
		foreach(i;0..n)
		{
			int k;
			input(&k);
			foreach(j;0..k)
			{
				int f;
				input(&f);
				g[f]~=i;
			}
		}
		int[int[]] q;
		foreach(i;g)
		{
			if(i.length)q[i.idup]++;
		}
		auto fact=(1L~iota(1L,5L*(10^^5)+1).array).cumulativeFold!"(a*b)%1000000007"(1L).array;
		long ans=1;
		foreach(i;q.byValue)
		{
			ans=(ans*fact[i])%mod;
		}
		writeln(ans);
	}
}

module main;
import std.bigint,std.container,std.array,std.algorithm,std.conv,
	std.functional,std.math,std.numeric,std.string,std.range,std.complex,
	std.typecons,std.regex,std.random,std.uni,std.traits,std.variant,
	std.stdio,std.bitmanip;
import core.stdc.stdio : freopen;
alias BitArray bitset;
alias RedBlackTree Rbt;
alias redBlackTree rbt;
alias BigInt big;
alias pair!(int,int) pii;
alias pair!(long,long) pll;
alias BoyerMooreFinder strfind;
alias make_pair mp;
alias binary_search bins;
alias orient_square orsq;
immutable int mod=1000000007;
pure nothrow
{
	T lcm (T)(auto ref T a,auto ref T b)
	{
		return a/gcd(a,b)*b;
	}
	X binpow(X,Y)(X base,Y exp)
		if(is(typeof(exp&1)))
	{
		if(exp<0)return X(0);
		X res=X(1);
		while(exp>0)
		{
			if(exp&1)res*=base;
			base*=base;
			exp>>=1;
		}
		return res;
	}
	auto binpow(X,Y,Z)(X base,Y exp,in Z mm)
		if(is(typeof(exp&1)))
	{
		if(mm==0) return binpow(base,exp);
		if(exp<0)return X(0);
		auto res=X(1)%mm;
		while(exp>0)
		{
			if(exp&1)res=(res*base)%mm;
			base*=base;
			base%=mm;
			exp>>=1;
		}
		return res;
	}
	@property X sqr(X)(in X a_) {return a_*a_;}
	@property X cub(X)(in X a_) {return a_*a_*a_;}
	size_t lowb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (!(a[l]<g))?l:r;
	}
	size_t upb(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(g<a[m])r=m;
			else l=m;
		}
		return (g<a[l])?l:r;
	}
	size_t binf(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		size_t l=0,r=a.length;
		while(r-l>1)
		{
			auto m=(l+r)>>1;
			if(!(a[m]<g))r=m;
			else l=m;
		}
		return (g==a[l])?l:a.length;
	}
	bool binary_search(T,X)(in T a,auto ref X g)
		if(isRandomAccessRange!T && hasLength!T && is(typeof(g<a[0])==bool))
	{
		return binf(a,g)!=a.length;
	}
	V foldr(R,V,T)(R range,T arg,V nach)
		if(isFunction!T && isInputRange!R && is(typeof(arg(nach,R.front))==V))
	{
		for(;!range.empty;range.popFront()) nach=arg(nach,range.front);
		return nach;
	}
	size_t countr(R,T)(R range,T fun)
		if(isFunction!T && isInputRange!R && is(typeof(fun(R.front))==bool))
	{
		size_t nach;
		for(;!range.empty;range.popFront()) nach+=fun(range.front);
		return nach;
	}
	T orient_square(T)(pair!(T,T)[] figure...)
	{
		auto n=figure.front,t=figure.front;
		figure.popFront();
		T ans=0;
		for(;!figure.empty;figure.popFront())
		{
			ans+=(figure.front.fi-t.fi)*(figure.front.se+t.se);
			t=figure.front;
		}
		return ans+(n.fi-t.fi)*(n.se+t.se);
	}
	real square(T)(pair!(T,T)[] figure...)
		if(is(typeof(figure.front*figure.front)==T))
	{
		return abs(orient_square(figure))/2.000000000000000;
	}
}
void putarr(X)(in X a,in char ch=' '){foreach(const ref i;a)write(i,ch);}
void putarr(X)(in X a,in size_t n,in size_t m)
{
	foreach(i;0..n)
	{
		foreach(j;0..m)write(a[i][j],' ');
		writeln;
	}
}
bool getarr(X)(X a,in size_t n)
{bool b=1; foreach(ref i;a[0..n])b=input(&i);return b;}
bool input(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length), ptrs)==ptrs.length;}
bool read(T...)(T ptrs) if (ptrs.length > 0)
{return readf(replicate(" %s", ptrs.length)~'\n', ptrs)==ptrs.length;}
struct pair(X,Y)
{
	X first;
	Y second;
	alias first fi;
	alias second se;
	this(X a_,Y b_){
		fi=a_;
		se=b_;
	}
	this(this){fi=fi;se=se;}
	this(A,B)(auto ref pair!(A,B) p) if(is(A:X) && is(B:Y))
	{
		fi=p.fi;
		se=p.se;
	}
	int opCmp(A,B)(in pair!(A,B) s_) const
		if(is(typeof(s_.fi<fi)==bool) && is(typeof(s_.se<se)==bool))
	{
		int cmp=0-(fi<s_.fi)+(fi>s_.fi);
		if(cmp!=0)return cmp;
		else return (0-(se<s_.se)+(se>s_.se));
	}
};
pair!(X,Y) make_pair(X,Y)(in X x_,in Y y_)
{
	pair!(X,Y) pp;
	pp.fi=x_;
	pp.se=y_;
	return pp;
}
nothrow void inf(in char* name) {freopen(name,"r",core.stdc.stdio.stdin);}
nothrow void ouf(in char* name) {freopen(name,"w",core.stdc.stdio.stdout);}
@property auto arread(T)(){return readln.split.map!(to!(T)).array;}
//split strip isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold schwartzSort multiSort partialSort heapify join filter countUntil
//---------------------------------------------------------------program beginning-----------------------------------------------------------------

void main()
{
	int n,m;
	loop:while(read(&n,&m))
	{
		auto g=new int[][m+1];
		foreach(i;0..n)
		{
			int k;
			input(&k);
			foreach(j;0..k)
			{
				int f;
				input(&f);
				g[f]~=i;
			}
		}
		int[int[]] q;
		foreach(i;g)
		{
			if(i.length)q[i.idup]++;
		}
		auto fact=1~iota(1,5*(10^^5)+1).cumulativeFold!"(a*b)%1000000007"(1).array;
		long ans=1;
		foreach(i;q.byValue)
		{
			ans=(ans*fact[i])%mod;
		}
		writeln(ans);
	}
}

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.typecons;

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

    auto idx = new int[] (m+1);
    int nxtid = 1;
    foreach (_; 0 .. n) {
        auto nrs = readln.chomp.split.map!(to!int).dropOne.array;

        int[int] cnt;

        foreach (e; nrs) { cnt[e] += 1; }

        int[][int] groups;
        foreach (p; cnt.byKeyValue) {
            groups[p.value] ~= p.key;
        }

        debug { groups.writeln; }

        foreach (arr; groups.values) {
            arr.schwartzSort!(x => idx[x]);

            debug { arr.writeln; }

            foreach (p, n; lockstep(arr, arr.dropOne)) {
                bool inc = idx[p] != idx[n];

                idx[p] = nxtid;

                if (inc) { nxtid += 1; }
            }

            idx[arr.back] = nxtid;

            ++nxtid;
        }
    }

    debug { idx.writeln; }

    auto grouped = idx.dropOne.sort.group.map!(t => t[1]);

    debug { grouped.writeln; }

    immutable int MD = 10 ^^ 9 + 23;

    auto fac = new int[] (m+1);
    fac[0] = 1;
    foreach (i; 1 .. m+1) { fac[i] = fac[i-1].to!long * i % MD; }

    auto ans = grouped.map!(x => fac[x])
        .fold!((x, y) => (x.to!long * y % MD).to!int)(1);

    ans.writeln;
}

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.typecons;

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

    auto idx = new int[] (m+1);
    int nxtid = 1;
    foreach (_; 0 .. n) {
        auto nrs = readln.chomp.split.map!(to!int).dropOne.array;

        int[int] cnt;

        foreach (e; nrs) { cnt[e] += 1; }

        int[][int] groups;
        foreach (p; cnt.byKeyValue) {
            groups[p.value] ~= p.key;
        }

        debug { groups.writeln; }

        foreach (arr; groups.values) {
            arr.schwartzSort!(x => idx[x]);

            debug { arr.writeln; }

            foreach (p, n; lockstep(arr, arr.dropOne)) {
                bool inc = idx[p] != idx[n];

                idx[p] = nxtid;

                if (inc) { nxtid += 1; }
            }

            idx[arr.back] = nxtid;
        }

        ++nxtid;
    }

    debug { idx.writeln; }

    auto grouped = idx.dropOne.sort.group.map!(t => t[1]);

    debug { grouped.writeln; }

    immutable int MD = 10 ^^ 9 + 23;

    auto fac = new int[] (m+1);
    fac[0] = 1;
    foreach (i; 1 .. m+1) { fac[i] = fac[i-1].to!long * i % MD; }

    auto ans = grouped.map!(x => fac[x])
        .fold!((x, y) => (x.to!long * y % MD).to!int)(1);

    ans.writeln;
}


Tree is a connected graph without cycles. A leaf of a tree is any vertex connected with exactly one other vertex.You are given a tree with n vertices and a root in the vertex 1. There is an ant in each leaf of the tree. In one second some ants can simultaneously go to the parent vertex from the vertex they were in. No two ants can be in the same vertex simultaneously except for the root of the tree.Find the minimal time required for all ants to be in the root of the tree. Note that at start the ants are only in the leaves of the tree.

The first line contains integer n (2 ≤ n ≤ 5·105) — the number of vertices in the tree. Each of the next n - 1 lines contains two integers xi, yi (1 ≤ xi, yi ≤ n) — the ends of the i-th edge. It is guaranteed that you are given the correct undirected tree.

Print the only integer t — the minimal time required for all ants to be in the root of the tree.

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

void dfs(int u, int v, int[][] neighbours, int[] depth, int* nDepth, int d)
{
	if (neighbours[v].length == 1) {
		depth[(*nDepth)++] = d;
	}
	else {
		foreach (int w; neighbours[v]) {
			if (w != u) {
				dfs(v, w, neighbours, depth, nDepth, d + 1);
			}
		}
	}
}

int solve(int v, int[][] neighbours)
{
	const int N = 500000;
	static int[] res = new int[N];
	int nLeafs = 0;

	dfs(0, v, neighbours, res, &nLeafs, 0);
	sort(res[0..nLeafs]);

	for (int i = 1; i < nLeafs; i++) {
		res[i] = max(res[i], res[i - 1] + 1);
	}

	return nLeafs == 0 ? 0 : res[nLeafs - 1];
}

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

	int[][] neighbours = new int[][n];
	int[] nNeighbours = new int[n];
	Tuple!(int, int)[] edges = new Tuple!(int, int)[n];

	for (int i = 0; i < n - 1; i++) {
		int u, v;
		scanf("%d%d", &u, &v);
		u--;
		v--;

		edges[i][0] = u;
		edges[i][1] = v;

		nNeighbours[u]++;
		nNeighbours[v]++;
	}

	for (int i = 0; i < n; i++) {
		neighbours[i] = new int[nNeighbours[i]];
		nNeighbours[i] = 0;
	}
	for (int i = 0; i < n - 1; i++) {
		int u = edges[i][0];
		int v = edges[i][1];

		neighbours[u][nNeighbours[u]++] = v;
		neighbours[v][nNeighbours[v]++] = u;
	}

	int res = 0;
	foreach (int v; neighbours[0]) {
		res = max(res, solve(v, neighbours) + 1);
	}

	printf("%d\n", res);
}


Polycarp is a great fan of television.He wrote down all the TV programs he is interested in for today. His list contains n shows, i-th of them starts at moment li and ends at moment ri.Polycarp owns two TVs. He can watch two different shows simultaneously with two TVs but he can only watch one show at any given moment on a single TV. If one show ends at the same moment some other show starts then you can't watch them on a single TV.Polycarp wants to check out all n shows. Are two TVs enough to do so?

The first line contains one integer n (1 ≤ n ≤ 2·105) — the number of shows. Each of the next n lines contains two integers li and ri (0 ≤ li < ri ≤ 109) — starting and ending time of i-th show.

If Polycarp is able to check out all the shows using only two TVs then print "YES" (without quotes). Otherwise, print "NO" (without quotes).

// Codeforces My Practice
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "s", int, "e");
    auto n = getNum!int;
    auto ap = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (_; 0..n) {
        auto se = getVals!int;
        ap.put(Tp(se[0], se[1]));
    }
    auto prgs = ap.data[];
    prgs.sort!"a.s < b.s";
    auto tv1 = Tp(-1,-1), tv2 = Tp(-1,-1);
    foreach (tp; prgs) {
        if (tv1.e < tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv2.e < tp.s) {
            tv2 = tp;
            continue;
        }
        writeln("NO");
        return;
    }
    writeln("YES");
}

module main;
__gshared:
import core.bitop, std.algorithm, std.bigint, std.bitmanip, std.complex,
	std.container, std.conv, std.datetime, std.functional, std.math, std.meta;
import std.numeric : Fft, fft, gcd, inverseFft;
import std.parallelism, std.random, std.range, std.regex, std.stdio, std.string,
	std.traits, std.typecons, std.uni, std.variant;

alias pair(X, Y) = Tuple!(X, "fi", Y, "se");
alias mp = make_pair;
alias pii = pair!(int, int);
alias pll = pair!(long, long);
alias gcd = std.numeric.gcd;
alias lint = long;
alias rbt = RedBlackTree;
///modulo
enum mod = 10 ^^ 9 + 7, mod2 = mod + 2;
public
{
	pure nothrow
	{
		///lcm
		T lcm(T)(auto ref T a, auto ref T b)
		{
			return a / gcd(a, b) * b;
		}
		///make_pair
		pair!(X, Y) make_pair(X, Y)(in X x_, in Y y_)
		{
			return tuple!(X, "fi", Y, "se")(x_, y_);
		}
		///BigInt greatest common divizor
		BigInt gcd(BigInt a, BigInt b)
		{
			while (b)
			{
				a %= b;
				swap(a, b);
			}
			return a;
		}
		///square
		@property X sqr(X)(in X a_)
		{
			return a_ * a_;
		}
		///cube
		@property X cub(X)(in X a_)
		{
			return a_ * a_ * a_;
		}
		///integer size
		int sz(T)(T a) if (hasLength!T)
		{
			return cast(int) a.length;
		}
		///posicion lower bound
		size_t lowb(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			size_t l = 0, r = a.length;
			while (r - l > 1)
			{
				auto m = (l + r) >> 1;
				if (!(a[m] < g))
					r = m;
				else
					l = m;
			}
			return (!(a[l] < g)) ? l : r;
		}
		///posicion upper bound
		size_t upb(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			size_t l = 0, r = a.length;
			while (r - l > 1)
			{
				auto m = (l + r) >> 1;
				if (g < a[m])
					r = m;
				else
					l = m;
			}
			return (g < a[l]) ? l : r;
		}
		///posicion binary search
		size_t binf(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			auto pos = lowb(a, g);
			return (g == a[pos]) ? pos : a.length;
		}
		///binary search
		bool binary_search(T, X)(T a, auto ref X g)
				if (isRandomAccessRange!T && hasLength!T && is(typeof(g < a[0]) == bool))
		{
			return binf(a, g) != a.length;
		}
	}
	///write an array
	void putarr(X)(in X a, in char ch = ' ') if (isInputRange!X)
	{
		writefln("%(%s" ~ ch ~ "%)", a);
	}
	///write a matrix
	void putarr(X)(in X a)
			if (isInputRange!X && isInputRange!(ElementType!X) && !isSomeString!(ElementType!X))
	{
		writefln("%(%(%s %)\n%)", a);
	}
	///get an array
	bool getarr(X)(X a, in size_t n)
	{
		bool b = 1;
		foreach (ref i; a[0 .. n])
			b = input(&i);
		return b;
	}
	///read without format
	bool input(T...)(ref T ptrs) if (ptrs.length > 0)
	{
		size_t s = 0;
		foreach (ref e; ptrs)
		{
			if (isSomeChar!(Unqual!(typeof(e))))
				s += readf(" %c", &e);
			else
				s += readf(" %s", &e);
		}
		return s == ptrs.length;
	}
	///readln without format
	bool read(T...)(ref T ptrs) if (ptrs.length > 0)
	{
		size_t s = 0;
		foreach (ref e; ptrs)
		{
			if (isSomeChar!(Unqual!(typeof(e))))
				s += readf(" %c", &e);
			else
				s += readf(" %s", &e);
		}
		readln;
		return s == ptrs.length;
	}
	///opening file
	nothrow auto inf(in char* name)
	{
		return freopen(name, "r", core.stdc.stdio.stdin);
	}
	///closing file
	nothrow auto ouf(in char* name)
	{
		return freopen(name, "w", core.stdc.stdio.stdout);
	}
	///parsing array from line
	@property auto arread(T)()
	{
		return readln.splitter.map!(to!(T)).array;
	}
	///outbuffer
	void enter(T...)(T args)
	{
		writeln(args);
		stdout.flush;
	}
}
//foreach_reverse isAlpha isNumber isWhite isLower isUpper toLower toUpper mixin
//cumulativeFold return static heapify join filter foreach
//------------------------------------------program beginning--------------------------

void main()
{
	version (home)
	{
		freopen("input.txt", "r", core.stdc.stdio.stdin);
		//freopen("output.txt", "w", core.stdc.stdio.stdout);
		/*StopWatch sw;
		sw.start;
		scope (exit)
		{
			sw.stop;
			stderr.writefln("\nTime: %d ms", sw.peek.msecs);
		}*/
	}
	int n;
	loop: while (read(n))
	{
		pii[] a;
		foreach (_; 0 .. n)
		{
			int l, r;
			read(l, r);
			a ~= mp(l, 0);
			a ~= mp(r, 1);
		}
		sort(a);
		int c;
		foreach (x; a)
		{
			if (x.se > 0)
				c--;
			else
				c++;
			if (c > 2)
			{
				writeln("NO");
				continue loop;
			}
		}
		writeln("YES");
	}
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "s", int, "e", int, "p");
    auto n = getNum!int;
    auto ap = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (i; 0..n) {
        auto se = getVals!int;
        ap.put(Tp(se[0], se[1], i));
    }
    auto prgs = ap.data[];
    prgs.sort!( (a, b) => a.s!=b.s ? a.s<b.s : (a.e!=b.e ? a.e<b.e : a.p<b.p) );
    auto tv1 = Tp(-1,-1,-1), tv2 = tv1;
    foreach (i,tp; prgs) {
        if (tv1.e < tp.s && tv2.e < tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv1.e < tp.s && tv2.e == tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv2.e < tp.s && tv1.e == tp.s) {
            tv2 = tp;
            continue;
        }
        writeln("NO");
        return;
    }
    writeln("YES");
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(long, "s", long, "e", long, "p");
    auto n = getNum!int;
    auto ap = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (i; 0..n) {
        auto se = getVals!long;
        ap.put(Tp(se[0], se[1], i));
    }
    auto prgs = ap.data[];
    prgs.sort!( (a, b) => a.s!=b.s ? a.s<b.s : (a.e!=b.e ? a.e<b.e : a.p<b.p) );
    auto tv1 = Tp(-1,-1,-1), tv2 = tv1;
    foreach (tp; prgs) {
        if (tv1.e < tp.s && tv2.e < tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv1.e < tp.s && tv2.e == tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv2.e < tp.s && tv1.e == tp.s) {
            tv2 = tp;
            continue;
        }
        writeln("NO");
        return;
    }
    writeln("YES");
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "s", int, "e");
    auto n = getNum!int;
    auto ap = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (_; 0..n) {
        auto se = getVals!int;
        ap.put(Tp(se[0], se[1]));
    }
    auto prgs = ap.data[];
    prgs.sort!"a.s < b.s";
    auto tv1 = Tp(-1,-1), tv2 = Tp(-1,-1);
    foreach (tp; prgs) {
        if (tv1.e < tp.s && tv2.e < tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv1.e <= tp.s && tv2.e == tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv2.e <= tp.s && tv1.e == tp.s) {
            tv2 = tp;
            continue;
        }
        writeln("NO");
        return;
    }
    writeln("YES");
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "s", int, "e");
    auto n = getNum!int;
    auto ap = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (_; 0..n) {
        auto se = getVals!int;
        ap.put(Tp(se[0], se[1]));
    }
    auto prgs = ap.data[];
    prgs.sort!"a.s < b.s";
    auto tv1 = Tp(-1,-1), tv2 = Tp(-1,-1);
    foreach (tp; prgs) {
        if (tv1.e < tp.s && tv2.e < tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv1.e < tp.s && tv2.e == tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv2.e < tp.s && tv1.e == tp.s) {
            tv2 = tp;
            continue;
        }
        writeln("NO");
        return;
    }
    writeln("YES");
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "s", int, "e", int, "p");
    auto n = getNum!int;
    auto ap = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (i; 0..n) {
        auto se = getVals!int;
        ap.put(Tp(se[0], se[1], i));
    }
    auto prgs = ap.data[];
    prgs.sort!( (a, b) => a.s!=b.s ? a.s<b.s : (a.e!=b.e ? a.e<b.e : a.p<b.p) );
    auto tv1 = Tp(-1,-1,-1), tv2 = tv1;
    foreach (i,tp; prgs) {
        if (tv1.e < tp.s && tv2.e < tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv1.s < 0 && tv2.e == tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv2.s < 0 && tv1.e == tp.s) {
            tv2 = tp;
            continue;
        }
        writeln("NO");
        return;
    }
    writeln("YES");
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "t", int, "p");
    auto n = getNum!int;
    auto startsAp = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (i; 0..n) {
        auto se = getVals!int;
        startsAp.put(Tp(se[0], i));
        endsAp.put(Tp(se[1], i));
    }
    auto starts = startsAp.data[];
    auto ends = endsAp.data[];
    starts.sort!"a.t < b.t";
    ends.sort!"a.t < b.t";
    auto tv1 = -1, tv2 = -1;
    auto useTv1 = false, useTv2 = false;
    while (starts.length > 0) {
        if (starts[0].t <= ends[0].t) {
            if (tv1 < 0) {
                tv1 = starts[0].p;
                useTv1 = true;
            } else if (tv2 < 0) {
                tv2 = starts[0].p;
                useTv2 = true;
            } else {
                writeln("NO");
                return;
            }
            starts = starts[1..$];
        } else if (starts[0].t > ends[0].t) {
            if (tv1 == ends[0].p) {
                tv1 = -1;
            } else if (tv2 == ends[0].p) {
                tv2 = -1;
            } else {
                writeln("NO");
                return;
            }
            ends = ends[1..$];
        }
    }
    writeln(useTv1 && useTv2 ? "YES" : "NO");
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "t", int, "p");
    auto n = getNum!int;
    auto startsAp = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (i; 0..n) {
        auto se = getVals!int;
        startsAp.put(Tp(se[0], i));
        endsAp.put(Tp(se[1], i));
    }
    auto starts = startsAp.data[];
    auto ends = endsAp.data[];
    starts.sort!( (a, b) => a.t == b.t ? a.p < b.p : a.t < b.t );
    ends.sort!( (a, b) => a.t == b.t ? a.p < b.p : a.t < b.t );
    auto tv1 = -1, tv2 = -1;
    while (starts.length > 0) {
        if (starts[0].t <= ends[0].t) {
            if (tv1 < 0) {
                tv1 = starts[0].p;
            } else if (tv2 < 0) {
                tv2 = starts[0].p;
            } else {
                writeln("NO");
                return;
            }
            starts = starts[1..$];
        } else {
            if (tv1 == ends[0].p) {
                tv1 = -1;
            } else if (tv2 == ends[0].p) {
                tv2 = -1;
            } else {
                writeln("NO");
                return;
            }
            ends = ends[1..$];
        }
    }
    writeln("YES");
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "t", int, "p");
    auto n = getNum!int;
    auto startsAp = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (i; 0..n) {
        auto se = getVals!int;
        startsAp.put(Tp(se[0], i));
        endsAp.put(Tp(se[1], i));
    }
    auto starts = startsAp.data[];
    auto ends = endsAp.data[];
    starts.sort!"a.t < b.t";
    ends.sort!"a.t < b.t";
    auto tv1 = -1, tv2 = -1;
    while (starts.length > 0) {
        if (starts[0].t <= ends[0].t) {
            if (tv1 < 0) {
                tv1 = starts[0].p;
            } else if (tv2 < 0) {
                tv2 = starts[0].p;
            } else {
                writeln("NO");
                return;
            }
            starts = starts[1..$];
        } else if (starts[0].t > ends[0].t) {
            if (tv1 == ends[0].p) {
                tv1 = -1;
            } else if (tv2 == ends[0].p) {
                tv2 = -1;
            } else {
                writeln("NO");
                return;
            }
            ends = ends[1..$];
        }
    }
    writeln("YES");
}

// Try Codeforces
// author: Leonardone @ NEETSDKASU
import std.stdio     : readln, writeln;
import std.string    : chomp;
import std.array     : split, appender;
import std.conv      : to;
import std.typecons  : Tuple;
import std.algorithm : sort;

auto gets() { return readln.chomp; }
auto getNum(T)() { return gets.to!T; }
auto getVals(T)() { return gets.split.to!(T[]); }

void main() {
    alias Tp = Tuple!(int, "s", int, "e", int, "p");
    auto n = getNum!int;
    auto ap = appender!(Tp[])();
    auto endsAp = appender!(Tp[])();
    foreach (i; 0..n) {
        auto se = getVals!int;
        ap.put(Tp(se[0], se[1], i));
    }
    auto prgs = ap.data[];
    prgs.sort!( (a, b) => a.s!=b.s ? a.s<b.s : (a.e!=b.e ? a.e<b.e : a.p<b.p) );
    auto tv1 = Tp(-1,-1,-1), tv2 = tv1;
    foreach (i,tp; prgs) {
        if (tv1.e < tp.s && tv2.e < tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv1.e < tp.s && tv2.e == tp.s) {
            tv1 = tp;
            continue;
        }
        if (tv2.e < tp.s && tv1.e == tp.s) {
            tv2 = tp;
            continue;
        }
        writeln("NO");
        return;
    }
    writeln(tv2.e < 0 ? "NO" : "YES");
}


This problem is given in two versions that differ only by constraints. If you can solve this problem in large constraints, then you can just write a single solution to the both versions. If you find the problem too difficult in large constraints, you can write solution to the simplified version only.Waking up in the morning, Apollinaria decided to bake cookies. To bake one cookie, she needs n ingredients, and for each ingredient she knows the value ai — how many grams of this ingredient one needs to bake a cookie. To prepare one cookie Apollinaria needs to use all n ingredients.Apollinaria has bi gram of the i-th ingredient. Also she has k grams of a magic powder. Each gram of magic powder can be turned to exactly 1 gram of any of the n ingredients and can be used for baking cookies.Your task is to determine the maximum number of cookies, which Apollinaria is able to bake using the ingredients that she has and the magic powder.

The first line of the input contains two positive integers n and k (1 ≤ n, k ≤ 1000) — the number of ingredients and the number of grams of the magic powder. The second line contains the sequence a1, a2, ..., an (1 ≤ ai ≤ 1000), where the i-th number is equal to the number of grams of the i-th ingredient, needed to bake one cookie. The third line contains the sequence b1, b2, ..., bn (1 ≤ bi ≤ 1000), where the i-th number is equal to the number of grams of the i-th ingredient, which Apollinaria has.

Print the maximum number of cookies, which Apollinaria will be able to bake using the ingredients that she has and the magic powder.

NoteIn the first sample it is profitably for Apollinaria to make the existing 1 gram of her magic powder to ingredient with the index 2, then Apollinaria will be able to bake 4 cookies.In the second sample Apollinaria should turn 1 gram of magic powder to ingredient with the index 1 and 1 gram of magic powder to ingredient with the index 3. Then Apollinaria will be able to bake 3 cookies. The remaining 1 gram of the magic powder can be left, because it can't be used to increase the answer.

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

auto readInts() {
	return array(map!(to!int)(readln().strip().split()));
}
auto readInt() {
	return readInts()[0];
}
auto readLongs() {
	return array(map!(to!long)(readln().strip().split()));
}
auto readLong() {
	return readLongs()[0];
}

void readlnTo(T...)(ref T t) {
    auto s = readln().split();
    assert(s.length == t.length);
    foreach(ref ti; t) {
        ti = s[0].to!(typeof(ti));
        s = s[1..$];
    }
}

const real eps = 1e-10;

void main(){
    long n, k;
    readlnTo(n ,k);
    auto a = readLongs();
    auto b = readLongs();
    long l = 0, u = 10000000000;
    while(u-l > 1) {
        auto m = (u+l)/2;
        auto t = k;
        foreach(i; iota(n.to!uint)) {
            if(m * a[i] > b[i]) {
                t -= m*a[i] - b[i];
            }
            if(t < 0) {
                break;
            }
        }
        if(t < 0) {
            u = m;
        } else {
            l = m;
        }
    }
    writeln(l);
}


Oleg the bank client lives in Bankopolia. There are n cities in Bankopolia and some pair of cities are connected directly by bi-directional roads. The cities are numbered from 1 to n. There are a total of m roads in Bankopolia, the i-th road connects cities ui and vi. It is guaranteed that from each city it is possible to travel to any other city using some of the roads.Oleg wants to give a label to each city. Suppose the label of city i is equal to xi. Then, it must hold that for all pairs of cities (u, v) the condition |xu - xv| ≤ 1 holds if and only if there is a road connecting u and v.Oleg wonders if such a labeling is possible. Find an example of such labeling if the task is possible and state that it is impossible otherwise.

The first line of input contains two space-separated integers n and m (2 ≤ n ≤ 3·105, 1 ≤ m ≤ 3·105) — the number of cities and the number of roads. Next, m lines follow. The i-th line contains two space-separated integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi) — the cities connected by the i-th road. It is guaranteed that there is at most one road between each pair of cities and it is possible to travel from any city to any other city using some roads.

If the required labeling is not possible, output a single line containing the string "NO" (without quotes). Otherwise, output the string "YES" (without quotes) on the first line. On the next line, output n space-separated integers, x1, x2, ..., xn. The condition 1 ≤ xi ≤ 109 must hold for all i, and for all pairs of cities (u, v) the condition |xu - xv| ≤ 1 must hold if and only if there is a road connecting u and v.

NoteFor the first sample, x1 = 2, x2 = 3, x3 = x4 = 1 is a valid labeling. Indeed, (3, 4), (1, 2), (1, 3), (1, 4) are the only pairs of cities with difference of labels not greater than 1, and these are precisely the roads of Bankopolia.For the second sample, all pairs of cities have difference of labels not greater than 1 and all pairs of cities have a road connecting them.For the last sample, it is impossible to construct a labeling satisfying the given constraints.

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, 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)); }

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto A = new int[M];
      auto B = new int[M];
      foreach (i; 0 .. M) {
        A[i] = readInt() - 1;
        B[i] = readInt() - 1;
      }

      auto G = new int[][N];
      foreach (i; 0 .. M) {
        G[A[i]] ~= i;
        G[B[i]] ~= i;
      }

      DList!int que;
      auto dist = new int[N];

      void bfs(int src) {
        dist[] = -1;
        dist[src] = 0;
        que ~= src;
        for (; !que.empty; ) {
          const u = que.front;
          que.removeFront;
          foreach (i; G[u]) {
            const v = A[i] ^ B[i] ^ u;
            if (dist[v] == -1) {
              dist[v] = dist[u] + 1;
              que ~= v;
            }
          }
        }
      }

      bfs(0);
      debug {
        writeln("dist = ", dist);
      }
      int um = dist.maxIndex;
      if (dist[um] == 1) {
        foreach (u; 1 .. N) {
          int[] vs;
          foreach (i; G[u]) {
            const v = A[i] ^ B[i] ^ u;
            if (u < v) {
              vs ~= v;
            }
          }
          vs.sort;
          foreach (v; u + 1 .. N) {
            if (!(v - u - 1 < vs.length && vs[v - u - 1] == v)) {
              // no edge uv
              um = u;
              goto found;
            }
          }
        }
      }
     found:
      bfs(um);
      debug {
        writeln("dist = ", dist);
      }

      auto touch2 = new bool[N];
      foreach (u; 0 .. N) {
        if (dist[u] == 2) {
          foreach (i; G[u]) {
            const v = A[i] ^ B[i] ^ u;
            touch2[v] = true;
          }
        }
      }
      foreach (u; 0 .. N) {
        if (dist[u] == 1 && !touch2[u]) {
          dist[u] = 0;
        }
      }

      bool ok = true;
      foreach (i; 0 .. M) {
        ok = ok && (abs(dist[A[i]] - dist[B[i]]) <= 1);
      }

      auto freq = new long[N];
      foreach (u; 0 .. N) {
        ++freq[dist[u]];
      }
      long m;
      foreach (d; 0 .. N) {
        m += freq[d] * (freq[d] - 1) / 2;
      }
      foreach (d; 0 .. N - 1) {
        m += freq[d] * freq[d + 1];
      }
      ok = ok && (m == M);

      if (ok) {
        writeln("YES");
        foreach (u; 0 .. N) {
          if (u > 0) write(" ");
          write(dist[u] + 1);
        }
        writeln;
      } else {
        writeln("NO");
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, 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)); }

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto A = new int[M];
      auto B = new int[M];
      foreach (i; 0 .. M) {
        A[i] = readInt() - 1;
        B[i] = readInt() - 1;
      }

      auto G = new int[][N];
      foreach (i; 0 .. M) {
        G[A[i]] ~= i;
        G[B[i]] ~= i;
      }

      DList!int que;
      auto dist = new int[N];

      void bfs(int src) {
        dist[] = -1;
        dist[src] = 0;
        que ~= src;
        for (; !que.empty; ) {
          const u = que.front;
          que.removeFront;
          foreach (i; G[u]) {
            const v = A[i] ^ B[i] ^ u;
            if (dist[v] == -1) {
              dist[v] = dist[u] + 1;
              que ~= v;
            }
          }
        }
      }

      bfs(0);
      const um = dist.maxIndex;
      bfs(um);
      debug {
        writeln("dist = ", dist);
      }

      bool ok = true;
      foreach (i; 0 .. M) {
        ok = ok && (abs(dist[A[i]] - dist[B[i]]) <= 1);
      }

      auto freq = new long[N];
      foreach (u; 0 .. N) {
        ++freq[dist[u]];
      }
      long m;
      foreach (d; 0 .. N) {
        m += freq[d] * (freq[d] - 1) / 2;
      }
      foreach (d; 0 .. N - 1) {
        m += freq[d] * freq[d + 1];
      }
      ok = ok && (m == M);

      if (ok) {
        writeln("YES");
        foreach (u; 0 .. N) {
          if (u > 0) write(" ");
          write(dist[u] + 1);
        }
        writeln;
      } else {
        writeln("NO");
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, 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)); }

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto A = new int[M];
      auto B = new int[M];
      foreach (i; 0 .. M) {
        A[i] = readInt() - 1;
        B[i] = readInt() - 1;
      }

      auto G = new int[][N];
      foreach (i; 0 .. M) {
        G[A[i]] ~= i;
        G[B[i]] ~= i;
      }

      DList!int que;
      auto dist = new int[N];

      void bfs(int src) {
        dist[] = -1;
        dist[src] = 0;
        que ~= src;
        for (; !que.empty; ) {
          const u = que.front;
          que.removeFront;
          foreach (i; G[u]) {
            const v = A[i] ^ B[i] ^ u;
            if (dist[v] == -1) {
              dist[v] = dist[u] + 1;
              que ~= v;
            }
          }
        }
      }

      bfs(0);
      const um = dist.maxIndex;
      bfs(um);
      debug {
        writeln("dist = ", dist);
      }

      auto touch2 = new bool[N];
      foreach (u; 0 .. N) {
        if (dist[u] == 2) {
          foreach (i; G[u]) {
            const v = A[i] ^ B[i] ^ u;
            touch2[v] = true;
          }
        }
      }
      foreach (u; 0 .. N) {
        if (dist[u] == 1 && !touch2[u]) {
          dist[u] = 0;
        }
      }

      bool ok = true;
      foreach (i; 0 .. M) {
        ok = ok && (abs(dist[A[i]] - dist[B[i]]) <= 1);
      }

      auto freq = new long[N];
      foreach (u; 0 .. N) {
        ++freq[dist[u]];
      }
      long m;
      foreach (d; 0 .. N) {
        m += freq[d] * (freq[d] - 1) / 2;
      }
      foreach (d; 0 .. N - 1) {
        m += freq[d] * freq[d + 1];
      }
      ok = ok && (m == M);

      if (ok) {
        writeln("YES");
        foreach (u; 0 .. N) {
          if (u > 0) write(" ");
          write(dist[u] + 1);
        }
        writeln;
      } else {
        writeln("NO");
      }
    }
  } catch (EOFException e) {
  }
}


You are given integer $$$n$$$. You have to arrange numbers from $$$1$$$ to $$$2n$$$, using each of them exactly once, on the circle, so that the following condition would be satisfied:For every $$$n$$$ consecutive numbers on the circle write their sum on the blackboard. Then any two of written on the blackboard $$$2n$$$ numbers differ not more than by $$$1$$$.For example, choose $$$n = 3$$$. On the left you can see an example of a valid arrangement: $$$1 + 4 + 5 = 10$$$, $$$4 + 5 + 2 = 11$$$, $$$5 + 2 + 3 = 10$$$, $$$2 + 3 + 6 = 11$$$, $$$3 + 6 + 1 = 10$$$, $$$6 + 1 + 4 = 11$$$, any two numbers differ by at most $$$1$$$. On the right you can see an invalid arrangement: for example, $$$5 + 1 + 6 = 12$$$, and $$$3 + 2 + 4 = 9$$$, $$$9$$$ and $$$12$$$ differ more than by $$$1$$$.

The first and the only line contain one integer $$$n$$$ ($$$1 \le n \le 10^5$$$).

If there is no solution, output "NO" in the first line.  If there is a solution, output "YES" in the first line. In the second line output $$$2n$$$ numbers — numbers from $$$1$$$ to $$$2n$$$ in the order they will stay in the circle. Each number should appear only once. If there are several solutions, you can output any of them.

NoteExample from the statement is shown for the first example. It can be proved that there is no solution in the second example.

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; }
// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int n = read.to!int;

	if(n % 2 == 0){
		"NO".writeln;
	}
	else{
		"YES".writeln;
		int[] ans = new int[](n * 2);
		foreach(i; 0 .. n){
			if(i % 2 == 0){
				ans[i] = i * 2 + 1;
				ans[n + i] = i * 2 + 2;
			}
			else{
				ans[i] = i * 2 + 2;
				ans[n + i] = i * 2 + 1;
			}
		}
		ans.map!(to!string).array.join(" ").writeln;
	}

}

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; }
// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
	int n = read.to!int;

	if(n % 2 == 0){
		"NO".writeln;
	}
	else{
		"YES".writeln;
		int[] ans = new int[](n * 2);
		foreach(i; 0 .. n){
			if(i % 2 == 0){
				ans[i] = i * 2 + 1;
				ans[n + i] = i * 2 + 2;
			}
			else{
				ans[i] = i * 2 + 2;
				ans[n + 1] = i * 2 + 1;
			}
		}
		ans.map!(to!string).array.join(" ").writeln;
	}

}


You are given four integers $$$n$$$, $$$B$$$, $$$x$$$ and $$$y$$$. You should build a sequence $$$a_0, a_1, a_2, \dots, a_n$$$ where $$$a_0 = 0$$$ and for each $$$i \ge 1$$$ you can choose:   either $$$a_i = a_{i - 1} + x$$$  or $$$a_i = a_{i - 1} - y$$$. Your goal is to build such a sequence $$$a$$$ that $$$a_i \le B$$$ for all $$$i$$$ and $$$\sum\limits_{i=0}^{n}{a_i}$$$ is maximum possible.

The first line contains a single integer $$$t$$$ ($$$1 \le t \le 10^4$$$) — the number of test cases. Next $$$t$$$ cases follow. The first and only line of each test case contains four integers $$$n$$$, $$$B$$$, $$$x$$$ and $$$y$$$ ($$$1 \le n \le 2 \cdot 10^5$$$; $$$1 \le B, x, y \le 10^9$$$). It's guaranteed that the total sum of $$$n$$$ doesn't exceed $$$2 \cdot 10^5$$$.

For each test case, print one integer — the maximum possible $$$\sum\limits_{i=0}^{n}{a_i}$$$.

NoteIn the first test case, the optimal sequence $$$a$$$ is $$$[0, 1, 2, 3, 4, 5]$$$.In the second test case, the optimal sequence $$$a$$$ is $$$[0, 10^9, 0, 10^9, 0, 10^9, 0, 10^9]$$$.In the third test case, the optimal sequence $$$a$$$ is $$$[0, -3, -6, 1, -2]$$$.

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 euDist(T)(T[] a, T[] b) { auto c = a.dup; c[] -= b[]; c[] *= c[]; return sqrt(cast(double)c.sum); }
double[] rotate(double[] vec, double rad) { return [cos(rad)*vec[0] - sin(rad)*vec[1], sin(rad)*vec[0] + cos(rad)*vec[1]]; }
double norm(double[] vec) { return sqrt(reduce!((a,b)=>a+b*b)(0.0, vec)); }
double dotProd(double[] a, double[] b) { auto r = a.dup; r[] *= b[]; return r.sum; }

//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); }

void main()
{
	auto t = RD!int;
	auto ans = new long[](t);
	foreach (ti; 0..t)
	{
		auto n = RD;
		auto B = RD;
		auto x = RD;
		auto y = RD;

		long z;
		foreach (i; 0..n)
		{
			if (z + x <= B)
				z += x;
			else
				z -= y;
			ans[ti] += z;
		}
	}

	foreach (e; ans)
		writeln(e);
	stdout.flush;
	debug readln;
}


You have a string $$$s$$$ consisting of $$$n$$$ characters. Each character is either 0 or 1.You can perform operations on the string. Each operation consists of two steps:  select an integer $$$i$$$ from $$$1$$$ to the length of the string $$$s$$$, then delete the character $$$s_i$$$ (the string length gets reduced by $$$1$$$, the indices of characters to the right of the deleted one also get reduced by $$$1$$$);  if the string $$$s$$$ is not empty, delete the maximum length prefix consisting of the same characters (the indices of the remaining characters and the string length get reduced by the length of the deleted prefix). Note that both steps are mandatory in each operation, and their order cannot be changed.For example, if you have a string $$$s =$$$ 111010, the first operation can be one of the following:  select $$$i = 1$$$: we'll get 111010 $$$\rightarrow$$$ 11010 $$$\rightarrow$$$ 010;  select $$$i = 2$$$: we'll get 111010 $$$\rightarrow$$$ 11010 $$$\rightarrow$$$ 010;  select $$$i = 3$$$: we'll get 111010 $$$\rightarrow$$$ 11010 $$$\rightarrow$$$ 010;  select $$$i = 4$$$: we'll get 111010 $$$\rightarrow$$$ 11110 $$$\rightarrow$$$ 0;  select $$$i = 5$$$: we'll get 111010 $$$\rightarrow$$$ 11100 $$$\rightarrow$$$ 00;  select $$$i = 6$$$: we'll get 111010 $$$\rightarrow$$$ 11101 $$$\rightarrow$$$ 01. You finish performing operations when the string $$$s$$$ becomes empty. What is the maximum number of operations you can perform?

The first line contains a single integer $$$t$$$ ($$$1 \le t \le 1000$$$) — the number of test cases. The first line of each test case contains a single integer $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$) — the length of the string $$$s$$$. The second line contains string $$$s$$$ of $$$n$$$ characters. Each character is either 0 or 1. It's guaranteed that the total sum of $$$n$$$ over test cases doesn't exceed $$$2 \cdot 10^5$$$.

For each test case, print a single integer — the maximum number of operations you can perform.

NoteIn the first test case, you can, for example, select $$$i = 2$$$ and get string 010 after the first operation. After that, you can select $$$i = 3$$$ and get string 1. Finally, you can only select $$$i = 1$$$ and get empty string.

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()
{
    int t;
    readf("%s", &t);
    readln;

    while (t--) {
        int n;
        readf("%s", &n);
        readln;

        auto s = readln.chomp;
        s ~= '2';
        int le = 0, r = 0;
        int ans = 0;
        while (le < n) {
            r = max(r, le);

            bool found = false;
            while (r+1 < n && s[r] != s[r+1]) { ++r; }
            found = r+1 < n;
            ++r;

            if (!found) {
                while (le < n && (le == n-1 || s[le] == s[le+1])) { ++le; }
                ++le;
            }

            while (le < n && (le == n-1 || s[le] == s[le+1])) { ++le; }
            ++le;

            ans += 1;
        }

        ans.writeln;
    }
}

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)); }

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

void main()
{
	auto t = RD!int;
	auto ans = new long[](t);
	foreach (ti; 0..t)
	{
		auto n = RD!int;
		auto s = RD!string;

		char last = s[0];
		int[] a;
		int cnt;
		foreach (i; 0..n)
		{
			if (s[i] == last)
				++cnt;
			else
			{
				a ~= cnt;
				cnt = 1;
				last = s[i];
			}
		}
		a ~= cnt;
		debug writeln(a);

		long c;
		foreach (e; a)
		{
			++c;
			auto x = min(e-1, c);
			c -= x;
			ans[ti] += x;
		}
		ans[ti] += (c+1) / 2;
	}

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


The BFS algorithm is defined as follows.  Consider an undirected graph with vertices numbered from $$$1$$$ to $$$n$$$. Initialize $$$q$$$ as a new queue containing only vertex $$$1$$$, mark the vertex $$$1$$$ as used.  Extract a vertex $$$v$$$ from the head of the queue $$$q$$$.  Print the index of vertex $$$v$$$.  Iterate in arbitrary order through all such vertices $$$u$$$ that $$$u$$$ is a neighbor of $$$v$$$ and is not marked yet as used. Mark the vertex $$$u$$$ as used and insert it into the tail of the queue $$$q$$$.  If the queue is not empty, continue from step 2.  Otherwise finish. Since the order of choosing neighbors of each vertex can vary, it turns out that there may be multiple sequences which BFS can print.In this problem you need to check whether a given sequence corresponds to some valid BFS traversal of the given tree starting from vertex $$$1$$$. The tree is an undirected graph, such that there is exactly one simple path between any two vertices.

The first line contains a single integer $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$) which denotes the number of nodes in the tree.  The following $$$n - 1$$$ lines describe the edges of the tree. Each of them contains two integers $$$x$$$ and $$$y$$$ ($$$1 \le x, y \le n$$$) — the endpoints of the corresponding edge of the tree. It is guaranteed that the given graph is a tree. The last line contains $$$n$$$ distinct integers $$$a_1, a_2, \ldots, a_n$$$ ($$$1 \le a_i \le n$$$) — the sequence to check.

Print "Yes" (quotes for clarity) if the sequence corresponds to some valid BFS traversal of the given tree and "No" (quotes for clarity) otherwise. You can print each letter in any case (upper or lower).

NoteBoth sample tests have the same tree in them.In this tree, there are two valid BFS orderings:   $$$1, 2, 3, 4$$$,  $$$1, 3, 2, 4$$$. The ordering $$$1, 2, 4, 3$$$ doesn't correspond to any valid BFS order.

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 G = new int[][](N);
    foreach (_; 0..N-1) {
        auto s = readln.split.map!(to!int);
        G[s[0]-1] ~= s[1]-1;
        G[s[1]-1] ~= s[0]-1;
    }
    auto A = readln.split.map!(x => x.to!int-1).array;

    auto D = new int[](N);
    auto E = new int[][](N);
    auto P = new int[](N);
    auto order = new int[](N);

    void dfs(int n, int p, int d) {
        P[n] = p;
        D[n] = d;
        E[d] ~= n;
        foreach (m; G[n]) if (m != p) dfs(m, n, d+1);
    }
    dfs(0, -1, 0);

    foreach (i; 0..N-1) {
        if (D[A[i]] > D[A[i+1]]) {
            writeln("No");
            return;
        }
    }

    foreach (i; 1..N) {
        if (D[A[i]] > D[A[i-1]]) {
            order[A[i]] = 0;
        } else {
            order[A[i]] = order[A[i-1]] + 1;
        }
    }

    foreach (i; 0..N-1) {
        if (D[A[i]] == D[A[i+1]] && order[P[A[i]]] > order[P[A[i+1]]]) {
            writeln("No");
            return;
        }
    }

    writeln("Yes");
}

import core.bitop;
import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.datetime;
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;
    readf("%s", &n);
    readln;

    auto g = new int[][] (n+1);
    foreach (_; 0 .. n-1) {
        int x, y;
        readf("%s %s", &x, &y);
        readln;

        g[x] ~= y;
        g[y] ~= x;
    }

    auto ord = readln.chomp.split.map!(to!int).array;
    if (ord.front != 1) {
        writeln("No");
        return;
    }

    auto nxt = make!(DList!(RedBlackTree!int));
    nxt ~= make!RedBlackTree(g[1]);
    foreach (e; ord.dropOne) {
        while (!nxt.empty && e !in nxt.front) {
            nxt.removeFront;
        }
        if (nxt.empty) {
            writeln("No");
            return;
        }

        nxt ~= make!RedBlackTree(g[e]);
    }

    writeln("Yes");
}

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

void main ()
{
	int n;
	while (readf (" %s", &n) > 0)
	{
		auto a = new int [] [n];
		foreach (i; 0..n - 1)
		{
			int u, v;
			readf (" %s %s", &u, &v);
			u -= 1;
			v -= 1;
			a[u] ~= v;
			a[v] ~= u;
		}
		readln;
		auto p = readln.splitter.map !(to !(int)).array;
		p[] -= 1;

		auto d = new int [n];
		auto r = new int [n];

		void recur (int v, int p, int depth)
		{
			d[v] = depth;
			r[v] = p;
			foreach (u; a[v])
			{
				if (u != p)
				{
					recur (u, v, depth + 1);
				}
			}
		}

		recur (0, n, 0);

		bool ok = true;
		scope (exit) {writeln (ok ? "Yes" : "No");}
		foreach (i; 1..n)
		{
			ok &= (d[p[i - 1]] <= d[p[i]]);
		}
		if (!ok)
		{
			continue;
		}

		auto q = new int [n];
		foreach (i, c; p)
		{
			q[c] = i;
		}
		foreach (j; 2..n)
		{
			int i = j - 1;
			auto u = p[i];
			auto v = p[j];
			if (r[u] != r[v])
			{
				ok &= (q[r[u]] < q[r[v]]);
			}
		}
	}
}

import core.bitop;
import std.algorithm;
import std.array;
import std.bitmanip;
import std.container;
import std.conv;
import std.datetime;
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;
    readf("%s", &n);
    readln;

    auto g = new int[][] (n+1);
    foreach (_; 0 .. n-1) {
        int x, y;
        readf("%s %s", &x, &y);
        readln;

        g[x] ~= y;
        g[y] ~= x;
    }

    auto ord = readln.chomp.split.map!(to!int).array;
    if (ord.front != 1) {
        writeln("No");
        return;
    }

    auto vis = new bool[] (n+1);
    auto nxt = make!(DList!(RedBlackTree!int));
    vis[1] = true;
    nxt ~= make!RedBlackTree(g[1]);
    foreach (e; ord.dropOne) {
        if (!e in nxt.front) {
            writeln("No");
            return;
        }
        nxt.front.removeKey(e);

        vis[e] = true;
        nxt ~= make!(RedBlackTree!int);
        foreach (u; g[e]) if (!vis[u]) nxt.back.insert(u);

        if (nxt.front.empty()) nxt.removeFront();
    }

    writeln("Yes");
}

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

void main ()
{
	int n;
	while (readf (" %s", &n) > 0)
	{
		auto a = new int [] [n];
		foreach (i; 0..n - 1)
		{
			int u, v;
			readf (" %s %s", &u, &v);
			u -= 1;
			v -= 1;
			a[u] ~= v;
			a[v] ~= u;
		}
		readln;
		auto p = readln.splitter.map !(to !(int)).array;
		p[] -= 1;

		auto d = new int [n];
		auto r = new int [n];

		void recur (int v, int p, int depth)
		{
			d[v] = depth;
			r[v] = p;
			foreach (u; a[v])
			{
				if (u != p)
				{
					recur (u, v, depth + 1);
				}
			}
		}

		recur (0, n, 0);

		bool ok = true;
		scope (exit) {writeln (ok ? "Yes" : "No");}
		foreach (i; 1..n)
		{
			ok &= (d[p[i - 1]] <= d[p[i]]);
		}
		if (!ok)
		{
			continue;
		}
		continue;

		auto q = new int [n];
		foreach (i, c; p)
		{
			q[c] = i;
		}
		foreach (j; 2..n)
		{
			int i = j - 1;
			auto u = p[i];
			auto v = p[j];
			if (r[u] != r[v])
			{
				ok &= (q[r[u]] < q[r[v]]);
			}
		}
	}
}