QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#143170#3310. Steel Slicing 2qLWA 21ms172976kbC++1434.9kb2023-08-20 20:15:042023-08-20 20:15:07

Judging History

你现在查看的是最新测评结果

  • [2023-08-20 20:15:07]
  • 评测
  • 测评结果:WA
  • 用时:21ms
  • 内存:172976kb
  • [2023-08-20 20:15:04]
  • 提交

answer

#include<cstdio>
#include<utility>
#include<cstdlib>
#include<type_traits>
#include<array>
#include<vector>
/**
 * 写得死烂,又长又慢。
 * Author:qL
 * todo:
 * Better modInt
 * frac
 * More Poly
 * fix bug of radix_sort
 * new IO
*/
namespace QL{
	/**
	 * 图方便用的
	*/
	namespace{
		using ll=long long;
		using ull=unsigned long long;
		using uint=unsigned int;
		using db=double;
		using ld=long double;
#if _GLIBCXX_USE_INT128
		using lll=__int128;
		using ulll=unsigned __int128;
#else
		using lll=long long;
		using ulll=unsigned long long;
#endif
#if _GLIBCXX_NUMERIC&&(__cplusplus>=201703L)
		template<typename _Tp>
		constexpr _Tp Inf=std::numeric_limits<_Tp>::max()/2;
#else
		constexpr int Inf=0x3f3f3f3f;
		constexpr long long llInf=0x3f3f3f3f3f3f3f3f;
		constexpr double dbInf=1e17;
		constexpr long double ldInf=1e22;
#endif
#ifndef _GLIBCXX_CMATH
	#define sqrt __builtin_sqrt
	#define sqrtf __builtin_sqrtf
	#define sqrtl __builtin_sqrtl
	#define ceil __builtin_ceil
	#define ceilf __builtin_ceilf
	#define ceill __builtin_ceill
	#define floor __builtin_floor
	#define floorf __builtin_floorf
	#define floorl __builtin_floorl
	#define log2 __builtin_log2
	#define log __builtin_log
	#define cos __builtin_cos
	#define sin __builtin_sin
	#define tan __builtin_tan
	#define acos __builtin_acos
#endif
#ifndef _GLIBCXX_CSTRING
	#define memset __builtin_memset
	#define memcpy __builtin_memcpy
	#define strlen __builtin_strlen
	#define strcmp __builtin_strcmp
#endif
#ifndef _GLIBCXX_CSTDIO
	#define fwrite __builtin_fwrite
	#define putchar __builtin_putchar
	#define fputc __builtin_fputc
	#define fputs __builtin_fputs
#endif
#ifndef likely
	#define likely(x) __builtin_expect(!!(x),1)
#endif
#ifndef unlikely
	#define unlikely(x) __builtin_expect(!!(x),0)
#endif
	}
	/**
	 * 不想多加头文件了……
	*/
	namespace Error{
		constexpr void make_re(int _seed_=114514){
			std::exit(_seed_);
		}
#ifndef _GLIBCXX_CASSERT
		constexpr bool assert(bool x,const char *reason){
			if(unlikely(!x)){
				fputs(reason,stderr);
				fputs(reason,stdout);
				make_re();
			}
			return false;
		}
		constexpr bool assert(bool x,char *reason){
			return assert(x,const_cast<const char *>(reason));
		}
		constexpr bool assert(bool x){
			if(unlikely(!x)){
				fputs("Assert: RE",stderr);
				fputs("Assert: RE",stdout);
				make_re();
			}
			return false;
		}
#endif
	}
	/**
	 * 这坨代码最让人难以理解的地方:没逝乱靠元编程库
	*/
	namespace Traits_Tools{
		template<typename _Tp>
		class has_member_swap{
		private:
			template<typename T>
			static auto Check(void)->decltype(std::declval<T>().swap(),std::true_type());
			template<typename T>
			static std::false_type Check(...);
		public:
			enum{value=std::is_same<decltype(Check<_Tp>(nullptr)),std::true_type>::value};
		};
		#define Operator_Check_Helper(name,opt) \
				template<typename _Tp1,typename _Tp2> \
				class has_operator_##name{ \
				private: \
					template<typename T1,typename T2> \
					static auto Check(void)->decltype(std::declval<T1,T2>().operator opt (),std::true_type()); \
					template<typename T1,typename T2> \
					static std::false_type Check(...); \
				public: \
					enum{value=std::is_same<decltype(Check<_Tp1,_Tp2>(nullptr)),std::true_type>::value}; \
				};
		Operator_Check_Helper(plus,+)
		Operator_Check_Helper(subtract,-)
		Operator_Check_Helper(multiply,*)
		Operator_Check_Helper(divide,/)
		Operator_Check_Helper(mod,%)
		Operator_Check_Helper(and,&)
		Operator_Check_Helper(or,|)
		Operator_Check_Helper(xor,^)
		#undef Operator_Check_Helper
		#define Is_Type_Helper(type) \
		template<typename _Tp> \
		constexpr bool is_##type =false; \
		template<> \
		constexpr bool is_##type < type > =true;
		Is_Type_Helper(bool)
		Is_Type_Helper(char)
		#undef Is_Type_Helper
		template<typename _Tp,
		typename std::enable_if<!is_bool<_Tp>&&std::is_integral<_Tp>::value>::type* =nullptr>
		struct to_signed_type;
		#define To_Signed_Helper(type) \
		template<> \
		struct to_signed_type< unsigned type >{ \
			using signed_type= type ; \
		}; \
		template<> \
		struct to_signed_type < type >{ \
			using signed_type= type; \
		};
		To_Signed_Helper(int)
		To_Signed_Helper(long long)
		#undef To_Signed_Helper
		template<typename _Tp,
		typename std::enable_if<!is_bool<_Tp>&&std::is_integral<_Tp>::value>::type* =nullptr>
		struct to_unsigned_type;
		#define To_Unsigned_Helper(type) \
		template<> \
		struct to_unsigned_type< type >{ \
			using unsigned_type=unsigned type; \
		}; \
		template<> \
		struct to_unsigned_type< unsigned type >{ \
			using unsigned_type=unsigned type; \
		};
		To_Unsigned_Helper(int)
		To_Unsigned_Helper(long long)
		#undef To_Unsigned_Helper
		template<typename _Tp,
		typename std::enable_if<!is_bool<_Tp>&&!is_char<_Tp>&&std::is_integral<_Tp>::value>::type* =nullptr>
		struct to_upper_type;
		#define To_Upper_Helper(type,upper) \
		template<> \
		struct to_upper_type< type >{ \
			using unsigned_type=upper; \
		}; \
		template<> \
		struct to_upper_type< u##type >{ \
			using unsigned_type=u##upper; \
		};
		To_Upper_Helper(int,ll)
		To_Upper_Helper(ll,lll)
		#undef To_Upper_Helper
	}
}
namespace QL{
	namespace Base_Tools{
		template<typename _Tp>
		static constexpr std::size_t integer_length=sizeof(_Tp)*10/sizeof(int);
		bool is_space(char ch){
			return ch==' ';
		}
		bool is_eoln(char ch){
#if (linux||__linux__||__linux)
			return ch=='\n'||ch=='\r';
#else
			return ch=='\n';
#endif
		}
		bool is_blank(char ch){
			return is_space(ch)||is_eoln(ch);
		}
		bool is_digit(char ch){
			switch(ch){
				case '0' ... '9': return true;
				default: return false;
			}
		}
		bool is_eof(char ch){
			return ch==EOF;
		}
	}
	namespace IO{
		using Base_Tools::integer_length;
		using Base_Tools::is_digit;
		using Base_Tools::is_space;
		using Base_Tools::is_eoln;
		using Base_Tools::is_blank;
		using Base_Tools::is_eof;
		/**
		 * fread+fwrite,-DLOACL for debug
		 * support:integer,floating,string,...
		 * todo:other
 		*/
		class IOstream{
		protected:
			using LIST=std::initializer_list<int>;
#ifndef LOCAL
			std::FILE *IN;
			std::FILE *OUT;
			static constexpr int SIZE=1<<15;
			char buf[SIZE]{},*p1{buf},*p2{buf},obuf[SIZE]{},*p3{obuf};
		public:
			char pull(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,SIZE,IN),p1==p2)?(Ch=EOF):*p1++;}
			void push(char ch){((p3-obuf)==SIZE&&(flush(false),0)),*p3++=ch;}
			template<std::size_t L>
			std::FILE *set_in(const char (&name)[L]){
				static char in[L+5]={};
				std::sprintf(in,"%s.in",name);
				return std::fopen(in,"r");
			}
			template<std::size_t L>
			std::FILE *set_out(const char (&name)[L]){
				static char out[L+5];
				std::sprintf(out,"%s.out",name);
				return std::fopen(out,"w");
			}
#else
		protected:
		public:
			char pull(){return std::getchar();}
			void push(char ch){putchar(ch);}
			void err(char ch){fputc(ch,stderr);}
			template<std::size_t L>
			void set_in(const char(&name)[L]){
				static char in[L+5]={};
				std::sprintf(in,"%s.in",name);
				std::freopen(in,"r",stdin);
			}
			template<std::size_t L>
			void set_out(const char(&name)[L]){
				static char out[L+5];
				std::sprintf(out,"%s.out",name);
				std::freopen(out,"w",stdout);
			}
#endif
		public:
#ifndef LOCAL
			IOstream():IN{stdin},OUT{stdout},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
			template<std::size_t L>
			IOstream(const char(&name)[L]):IN{set_in(name)},OUT{set_out(name)},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
			template<std::size_t L>
			IOstream(const char(&name)[L],bool in,bool out):IN{in?set_in(name):stdin},OUT{out?set_out(name):stdout},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
			template<std::size_t L>
			IOstream(char(&name)[L]):IN{set_in(name)},OUT{set_out(name)},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
			template<std::size_t L>
			IOstream(char(&name)[L],bool in,bool out):IN{in?set_in(name):stdin},OUT{out?set_out(name):stdout},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
			~IOstream(){flush();}
			void flush(bool _flush_=false){
				if(likely(p3!=obuf))
					fwrite(obuf,1,p3-obuf,OUT),p3=obuf;
				if(_flush_) std::fflush(stdout);
			}
#else
			IOstream(){}
			template<std::size_t L>
			IOstream(const char(&name)[L]):Ch{'\n'}{reset_stdin(name),reset_stdout(name);}
			template<std::size_t L>
			IOstream(const char(&name)[L],bool in,bool out):Ch{'\n'}{in&&(reset_stdin(name),0),out&&(reset_stdout(name),0);}
			template<std::size_t L>
			IOstream(char(&name)[L]):Ch{'\n'}{reset_stdin(name),reset_stdout(name);}
			template<std::size_t L>
			IOstream(char(&name)[L],bool in,bool out):Ch{'\n'}{in&&(reset_stdin(name),0),out&&(reset_stdout(name),0);}
			void flush(){std::fflush(stdout);}
#endif
			template<typename T>
			T read(){
				T x;
				read(x);
				return x;
			}
protected:
			char Ch='\n';
public:
			bool eof(void)const{
				return Ch==EOF;
			}
			template<typename T>
			void read(T &&x,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr,typename std::enable_if<std::is_signed<T>::value,void>::type* =nullptr){
				x=0;bool flag=0;
				for(;!is_digit(Ch)&&!is_eof(Ch);Ch=pull()) if(Ch=='-') flag=1;
				if(is_eof(Ch)) return;
				if(flag) for(;is_digit(Ch);Ch=pull()) x=x*10-(Ch&15);
				else for(;is_digit(Ch);Ch=pull()) x=x*10+(Ch&15);
			}
			template<typename T>
			void read(T &&x,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr,typename std::enable_if<std::is_unsigned<T>::value,void>::type* =nullptr){
				x=0;
				for(;!is_digit(Ch)&&!is_eof(Ch);Ch=pull());
				if(is_eof(Ch)) return;
				for(;is_digit(Ch);Ch=pull()) x=x*10+(Ch&15);
			}
			void read(char *str){
				for(;is_blank(Ch);Ch=pull());
				if(is_eof(Ch)) return (void)(*str='\0');
				for(;!is_blank(Ch)&&!is_eof(Ch);Ch=pull()) *str++=Ch;
				*str='\0';
			}
			void read(char &c){
				c=Ch;
				for(;is_blank(c)&&!is_eof(c);c=pull());
				if(is_eof(c)) return;
				Ch=pull();
			}
			void read(bool &x){
				for(;Ch!='0'&&Ch!='1'&&!is_eof(Ch);Ch=pull());
				if(is_eof(Ch)) return void(x=false);
				x=Ch=='1';
				Ch=pull();
			}
			template<typename T>
			void read(T &&x,typename std::enable_if<std::is_floating_point<T>::value,void*>::type* =nullptr){
				static char str[114];
				read(str);
				x=std::atof(str);
			}
			template<typename T>
			void read(T &x){read(std::move(x));}
		protected:
			void(IOstream::*outchar)(char)=&IO::IOstream::push;
			template<typename T>
			void out(T x,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr,typename std::enable_if<std::is_signed<T>::value,void>::type* =nullptr){
				static char sta[integer_length<T>];
				int top=0;
				if(x<0){
					(this->*outchar)('-');
					do sta[top++]=((-x)%10)|48,x/=10;
					while(x);
				}
				else{
					do sta[top++]=(x%10)|48,x/=10;
					while(x);
				}
				while(top) (this->*outchar)(sta[--top]);
			}
			template<typename T>
			void out(T x,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr,typename std::enable_if<std::is_unsigned<T>::value,void>::type* =nullptr){
				static char sta[integer_length<T>];
				int top=0;
				do sta[top++]=(x%10)|48,x/=10;
				while(x);
				while(top) (this->*outchar)(sta[--top]);
			}
			void out(bool x){(this->*outchar)(x?'1':'0');}
			void out(char x){(this->*outchar)(x);}
			void out(char *str){
				out(reinterpret_cast<const char *>(str));
			}
			void out(const char *str){
				while(*str!='\0') (this->*outchar)(*str++);
			}
			/**
			 * ssprintf is awful...
			 */
			void out(float x){
				static char str[114];
				std::sprintf(str,"%f",x);
				out(str);
			}
			void out(double x){
				static char str[114];
				std::sprintf(str,"%f",x);
				out(str);
			}
			void out(long double x){
				static char str[114];
				std::sprintf(str,"%Lf",x);
				out(str);
			}
			void out(std::pair<int,float> x){
				static char str[114],opt[10];
				std::sprintf(opt,"%%.%df",x.first);
				std::sprintf(str,opt,x.second);
				out(str);
			}
			void out(std::pair<int,double> x){
				static char str[114],opt[10];
				std::sprintf(opt,"%%.%df",x.first);
				std::sprintf(str,opt,x.second);
				out(str);
			}
			void out(std::pair<int,long double> x){
				static char str[114],opt[10];
				std::sprintf(opt,"%%.%dLf",x.first);
				std::sprintf(str,opt,x.second);
				out(str);
			}
			void set_std_out(){outchar=&IO::IOstream::push;}
#ifdef LOCAL
			void set_err_out(){outchar=&IO::IOstream::err;}
#endif
		public:
			template<typename...Args>
			void read(Args &&...args){(void)LIST{(read(args),0)...};}
			template<typename...Args>
			void write(Args...args){set_std_out(),(void)LIST{(out(args),0)...};}
			template<typename...Args>
			void writeln(Args...args){write(args...),push('\n');}
#ifdef LOCAL
			template<typename...Args>
			void error(Args...args){set_err_out(),(void)LIST{(out(args),0)...};}
			template<typename...Args>
			void errorln(Args...args){error(args...),err('\n');}
#endif
		};
		IOstream lq;
	}
}
namespace QL{
	namespace rel_ops{
		namespace Calc_Self{
			#define Calc_Self_Helper(opt) \
			template<typename _Tp1,typename _Tp2> \
			constexpr _Tp1 &operator opt##=(_Tp1 &lhs,const _Tp2 &rhs){ \
				return lhs=(lhs opt rhs); \
			}
			Calc_Self_Helper(+)
			Calc_Self_Helper(-)
			Calc_Self_Helper(*)
			Calc_Self_Helper(/)
			Calc_Self_Helper(%)
			Calc_Self_Helper(&)
			Calc_Self_Helper(|)
			Calc_Self_Helper(^)
			#undef Calc_Self_Helper
		}
		namespace Compare{
			template<typename _Tp1,typename _Tp2>
			constexpr bool operator!=(const _Tp1 &lhs,const _Tp2 &rhs){
				return !(lhs==rhs);
			}
			template<typename _Tp1,typename _Tp2>
			constexpr bool operator<=(const _Tp1 &lhs,const _Tp2 &rhs){
				return (lhs==rhs)||(lhs<rhs);
			}
			template<typename _Tp1,typename _Tp2>
			constexpr bool operator>(const _Tp1 &lhs,const _Tp2 &rhs){
				return !((lhs==rhs)||(lhs<rhs));
			}
			template<typename _Tp1,typename _Tp2>
			constexpr bool operator>=(const _Tp1 &lhs,const _Tp2 &rhs){
				return !(lhs<rhs);
			}
		}
	}
	namespace Base_Tools{
		template<typename _Tp1,typename _Tp2>
		constexpr auto min(_Tp1 x,_Tp2 y){
			return x<y?x:y;
		}
		template<typename _Tp,typename ...Args>
		constexpr auto min(_Tp x,Args ...args){
			return min(x,min(args...));
		}
		template<typename _Tp1,typename _Tp2>
		constexpr auto max(_Tp1 x,_Tp2 y){
			return y<x?x:y;
		}
		template<typename _Tp,typename ...Args>
		constexpr auto max(_Tp x,Args ...args){
			return max(x,max(args...));
		}
		template<typename _Tp1,typename _Tp2>
		constexpr bool chkmin(_Tp1 &x,_Tp2 y){
			return y<x?(x=y,true):false;
		}
		template<typename _Tp1,typename _Tp2,typename...Args>
		constexpr bool chkmin(_Tp1 &x,_Tp2 y,Args ...args){
			return chkmin(x,y)|chkmin(x,args...);
		}
		template<typename _Tp1,typename _Tp2>
		constexpr bool chkmax(_Tp1 &x,_Tp2 y){
			return x<y?(x=y,true):false;
		}
		template<typename _Tp1,typename _Tp2,typename...Args>
		constexpr bool chkmax(_Tp1 &x,_Tp2 y,Args ...args){
			return chkmax(x,y)|chkmax(x,args...);
		}
		template<typename _Tp>
		constexpr void swap(_Tp &x,_Tp &y,typename std::enable_if<!Traits_Tools::has_member_swap<_Tp>::value>::type* =nullptr){
			_Tp tmp;
			tmp=x,x=y,y=tmp;
		}
		template<typename _Tp,typename std::enable_if<std::is_integral<_Tp>::value>::type* =nullptr>
		constexpr void swap(_Tp &x,_Tp &y){
			x!=y&&(x^=y^=x^=y);
		}
		template<typename _Tp>
		constexpr void swap(_Tp *&x,_Tp *&y){
			_Tp *tmp;
			tmp=x,x=y,y=tmp;
		}
		template<typename _Tp,typename std::enable_if<Traits_Tools::has_member_swap<_Tp>::value>::type* =nullptr>
		constexpr void swap(_Tp &x,_Tp &y){
			x.swap(y);
		}
		template<typename _Tp>
		constexpr _Tp abs(const _Tp &x){
			return x<0?-x:x;
		}
	}
	/**
	 * gcd is 1 for floating
	*/
	namespace Math_Tools{
		namespace Math_Tools_base{
			template<typename _Tp,typename _Used>
			constexpr _Tp qpow(ll x,_Used p,_Tp mod){
				_Tp ret=1;
				for(;p;p>>=1,x=x*x%mod) if(p&1) ret=ret*x%mod;
				return ret;
			}
		}
		template<typename _Tp,typename _Used>
		constexpr _Tp qpow(_Tp x,_Used p,_Tp mod){
			return Math_Tools_base::qpow(x,p,mod);
		}
		template<typename _Tp,typename _Used>
		constexpr _Tp qpow(_Tp x,_Used p){
			_Tp ret=1;
			for(;p;p>>=1,x=x*x) if(p&1) ret=ret*x;
			return ret;
		}
		template<typename _Tp>
		constexpr _Tp inv(_Tp x,_Tp mod){
			return Math_Tools_base::qpow(x,mod-2,mod);
		}
		template<typename _Tp>
		constexpr auto gcd(_Tp a,_Tp b,typename std::enable_if<std::is_integral<_Tp>::value>::type* =nullptr){
			return b?gcd(b,a%b):a;
		}
		template<typename _Tp>
		constexpr auto gcd(_Tp a,_Tp b,typename std::enable_if<std::is_floating_point<_Tp>::value>::type* =nullptr){
			return 1;
		}
		template<typename _Tp>
		constexpr auto lcm(_Tp a,_Tp b){
			return a/gcd(a,b)*b;
		}
	}
	/**
	 * 本实现的亮点是支持不定模数(不用遍历地进行初始化)
	 * 需要实现一个类,重载const类型的()运算符返回模数
	 * 实现可参考QL::ModNumber::Moder
	 * 模数有问题可以重载inv
	 * 其他的不知道了,似乎不是很快,要卡常的可以套约减器
	 * (用这玩意儿也就图个方便)
	 * upd:塞进去了个barrett约减,更慢了(乐
	 * 跑不过编译器优化,它是蒙哥马利吗……
	 */
	namespace ModNumber{
		template<typename _Tp>
		struct Barrett{
			_Tp mod;
			ulll used;
			Barrett(){}
			Barrett(_Tp _mod):mod{_mod},used{(ulll(1)<<63)/mod}{}
			constexpr void ReInit(_Tp _mod){
				mod=_mod;
				used=(ulll(1)<<63)/mod;
			}
			constexpr _Tp calc(ll x)const{
				return (x=x-mod*((x*used)>>63))<mod?x:x-mod;
			}
		};
		template<typename _Tp>
		struct Moder{
			template<typename _Tp_>
			constexpr void chk_val(_Tp_ &val)const{
				val<0?(val+=getmod()):(val<getmod()?0:val-=getmod());
			}
			virtual const _Tp getmod(void)const{
				return _Tp(998244353);
			}
			virtual const _Tp operator()(void)const{
				return getmod();
			}
			virtual const _Tp calc(ll x)const{
				return x%getmod();
			}
			template<typename _Tp1,typename _Tp2>
			constexpr _Tp plus(const _Tp1 &x,const _Tp2 &y)const{
				return calc(x+y);
			}
			template<typename _Tp1,typename _Tp2>
			constexpr _Tp mul(const _Tp1 &x,const _Tp2 &y)const{
				return calc(ll(x)*y);
			}
			constexpr _Tp qpow(ll a,int x)const{
				_Tp ret=1;
				for(;x;x>>=1,a=calc(a*a)) if(x&1) ret=calc(ret*a);
				return ret;
			}
			template<typename _Tp_>
			constexpr _Tp inv(const _Tp_ &x)const{
				return qpow(x,getmod()-2);
			}
		};
		template<typename _Moder>
		class modInt{
		protected:
			static _Moder mod;
			int v;
		public:
			constexpr modInt():v{}{}
			template<typename _Tp_>
			constexpr modInt(const _Tp_ &_v):v(_v%mod()){mod.chk_val(v);}
			template<typename _Tp_>
			constexpr explicit operator _Tp_()const{
				return _Tp_(v);
			}
			constexpr modInt operator-()const{
				return modInt(mod()-v);
			}
			constexpr modInt operator+(const modInt &y)const{
				return mod.plus(v,y.v);
			}
			constexpr modInt operator-(const modInt &y)const{
				return *this+(-y);
			}
			constexpr modInt operator*(const modInt &y)const{
				return mod.mul(v,y.v);
			}
			constexpr modInt operator/(const modInt &y)const{
				return mod.mul(v,mod.inv(y.v));
			}
			template<typename T>
			constexpr modInt operator^(const modInt<T> &y)const{
				return mod.qpow(v,int(y));
			}
			#define MODINT_T_HELPER(opt) \
			template<typename T> \
			constexpr friend modInt operator opt (const modInt &x,const T &y){ \
				return x opt modInt(y); \
			}
			MODINT_T_HELPER(+)
			MODINT_T_HELPER(-)
			MODINT_T_HELPER(*)
			MODINT_T_HELPER(/)
			MODINT_T_HELPER(^)
			#undef MODINT_T_HELPER
			#define MODINT_REV_HELPER(opt) \
			template<typename T> \
			constexpr friend modInt operator opt (const T &x,const modInt &y){ \
				return modInt(x) opt y; \
			}
			MODINT_REV_HELPER(+)
			MODINT_REV_HELPER(-)
			MODINT_REV_HELPER(*)
			MODINT_REV_HELPER(/)
			#undef MODINT_REV_HELPER
			template<typename T>
			constexpr friend bool operator<(const T &x,const modInt &y){
				return x<y.v;
			}
			template<typename T>
			constexpr bool operator<(const T &y)const{
				return v<y;
			}
			template<typename T>
			constexpr friend bool operator==(const T &x,const modInt &y){
				return x==y.v;
			}
			template<typename T>
			constexpr bool operator==(const T &y)const{
				return v==y;
			}
			constexpr modInt &operator++(){
				mod.chk_val(++v);
				return *this;
			}
			constexpr modInt operator++(int){
				modInt ret=*this;
				mod.chk_val(++v);
				return ret;
			}
			constexpr modInt &operator--(){
				mod.chk_val(--v);
				return *this;
			}
			constexpr modInt operator--(int){
				modInt ret=*this;
				mod.chk_val(--v);
				return ret;
			}
		};
		template<typename _Moder>
		_Moder modInt<_Moder>::mod;
	}
	/**
	 * 一个不成型的东西
	 * 日后补全
	 */
	namespace FracNumber{
		using Math_Tools::lcm;
		using Math_Tools::gcd;
		template<typename _Tp>
		class frac{
		protected:
			_Tp x,y;
			constexpr void chk_self(){
				_Tp _gcd_=gcd(x,y);
				if(_gcd_!=1) x/=_gcd_,y/=_gcd_;
			}
		public:
			constexpr frac():x{},y{}{}
			template<typename T>
			constexpr frac(T num,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr):x(num),y(1){}
			template<typename T>
			constexpr frac(T _x,T _y,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr):x(_x),y(_y){chk_self();}
			template<typename T>
			constexpr explicit operator T()const{
				return T(x)/y;
			}
			template<typename T>
			constexpr bool operator<(const frac<T> &it)const{
				auto _lcm_=lcm(y,it.y);
				return x*(_lcm_/y)<it.x*(_lcm_/it.y);
			}
		};
	}
	/**
	 * 多项式,占坑
	 * 以后会尽量补全的
	 */
	namespace Poly_Tools{
		namespace ComplexNumber{
			template<typename _Tp>
			struct complex{
				_Tp real,imag;
				constexpr complex():real{},imag{}{}
				template<typename T>
				constexpr complex(const T &_real):real(_real),imag{}{}
				template<typename T1,typename T2>
				constexpr complex(const T1 &_real,const T2 &_imag):real(_real),imag(_imag){}
				template<typename T>
				constexpr complex(const complex<T> &it):real(it.real),imag(it.imag){}
				constexpr complex operator+(const complex &it)const{
					return complex(real+it.real,imag+it.imag);
				}
				constexpr complex operator-(const complex &it)const{
					return complex(real-it.real,imag-it.imag);
				}
				constexpr complex operator*(const complex &it)const{
					return complex(real*it.real-imag*it.imag,imag*it.real+real*it.imag);
				}
			};
		}
		namespace Primitive_Root{
			using Math_Tools::qpow;
			template<uint P,uint G>
			static constexpr std::array<uint,20> init_for_pr(void){
				std::array<uint,20> ret{};
				for(uint i(0);i<20;++i) ret[i]=qpow(G,(P-1)/(qpow(2,i)));
				return ret;
			}
			template<uint P,uint G>
			struct PR{
				static constexpr uint p{P};
				static constexpr std::array<uint,20> g{init_for_pr<P,G>()};
			};
			using G_998244353=PR<998244353,3>;
			using G_1004535809=PR<1004535809,3>;
			using G_469762049=PR<469762049,3>;
		}
		/**
		 * 暴力乘法(划掉)
		 * upd:FFT
		 */
		using Base_Tools::swap;
		using Base_Tools::max;
		using Complex=ComplexNumber::complex<db>;
		using namespace rel_ops::Calc_Self;
		namespace Poly_Base{
			constexpr uint max_len=2<<20;
			class Poly_base{
			private:
				static constexpr uint pw[]{0,1,2,4,8,16,32,64,128,256,512,1024};
			protected:
				static uint rev[max_len];
				void ReInit(uint n){
					for(uint i(0);i<n;++i) rev[i]=(rev[i>>1]>>1)|((i&1)?(n>>1):0);
				}
				constexpr uint to_up(uint x)const{
					#define cs(x) case pw[x] ... pw[x+1]-1: return pw[x+1];
					switch(x){
						cs(0)cs(1)cs(2)cs(3)cs(4)cs(5)cs(6)cs(7)cs(8)cs(9)cs(10)
						default: return 1u<<(32-__builtin_clz(x));
					}
					#undef cs
				}
				static constexpr db PI=acos(-1);
			};
			uint Poly_base::rev[max_len];
			template<typename _Tp>
			class Poly:public virtual Poly_base{
			protected:
				_Tp *p;
				uint n;
			public:
				constexpr uint length(void)const{return n;}
				constexpr Poly():p{},n{}{}
				constexpr Poly(const uint &_n):p{new _Tp[_n]{}},n{_n}{}
				constexpr Poly(const std::initializer_list<_Tp> &L){
					delete[] p;
					p=new _Tp[L.size()]{},n=0;
					for(auto it:L) p[n++]=it;
				}
				constexpr Poly(const Poly &it):n{it.n}{
					p=new _Tp[it.n]{},n=it.n;
					memcpy(p,it.p,sizeof(_Tp)*it.n);
				}
				constexpr void resize(const uint &_n){
					delete[] p;
					p=new _Tp[_n]{},n=_n;
				}
				constexpr Poly &operator=(const Poly &it){
					if(this==&it) return *this;
					delete[] p;
					p=new _Tp[it.n]{},n=it.n;
					memcpy(p,it.p,sizeof(_Tp)*it.n);
					return *this;
				}
				constexpr _Tp &operator[](const uint &x){
					if(x>=n) Error::make_re();
					return p[x];
				}
				constexpr const _Tp &operator[](const uint &x)const{
					if(x>=n) Error::make_re();
					return p[x];
				}
				~Poly(){
					delete[] p;
				}
			};
		}
		using Poly_Base::max_len;
		using Poly_Base::Poly;
		template<typename _Tp>
		class FFT:public Poly<_Tp>{
		private:
			static Complex f[max_len];
		protected:
			constexpr void FFT_transform(Complex *f,uint n,int type){
				for(uint i(0);i<n;++i) if(i<Poly<_Tp>::rev[i]) swap(f[i],f[Poly<_Tp>::rev[i]]);
				for(uint p(1),l(2);l<=n;p=l,l<<=1){
					Complex step(cos(Poly<_Tp>::PI/p),type*sin(Poly<_Tp>::PI/p));
					for(uint i(0);i<n;i+=l){
						Complex *g=f+i,*h=g+p,w(1,0),t;
						for(uint k(0);k<p;++k,w*=step)
							t=h[k]*w,h[k]=g[k]-t,g[k]=g[k]+t;
					}
				}
			}
		public:
			constexpr FFT():Poly<_Tp>(){}
			constexpr FFT(const Poly<_Tp> &poly):Poly<_Tp>(poly){}
			constexpr Poly<_Tp> operator*(const FFT<_Tp> &it){
				Poly<_Tp> ret(Poly<_Tp>::n+it.length()-1);
				uint x(Poly<_Tp>::to_up(ret.length()));
				for(uint i(0);i<x;++i) f[i]=Complex(0,0);
				for(uint i(0);i<Poly<_Tp>::n;++i) f[i].real=Poly<_Tp>::p[i];
				for(uint i(0);i<it.length();++i) f[i].imag=it[i];
				Poly<_Tp>::ReInit(x);
				FFT_transform(f,x,1);
				for(uint i(0);i<x;++i) f[i]*=f[i];
				FFT_transform(f,x,-1);
				for(uint i(0);i<ret.length();++i) ret[i]=f[i].imag/x/2.0+0.5;
				return ret;
			}
		};
		template<typename _Tp>
		Complex FFT<_Tp>::f[max_len];
		using namespace Primitive_Root;
		template<typename _Tp>
		class NTT:public Poly<_Tp>{
		protected:
			static uint f[max_len];
			constexpr void NTT_transform(uint *f,uint n,int type){
				for(uint i(0);i<n;++i) if(i<Poly<_Tp>::rev[i]) swap(f[i],f[Poly<_Tp>::rev[i]]);
				for(uint p(1),l(2);l<=n;p=l,l<<=1){
					// uint step(cos(Poly<_Tp>::PI/p),type*sin(Poly<_Tp>::PI/p));
					// for(uint i(0);i<n;i+=l){
					// 	uint *g=f+i,*h=g+p,w(1,0),t;
					// 	for(uint k(0);k<p;++k,w*=step)
					// 		t=h[k]*w,h[k]=g[k]-t,g[k]=g[k]+t;
					// }
				}
			}
		public:
			constexpr NTT():Poly<_Tp>(){}
			constexpr NTT(const Poly<_Tp> &poly):Poly<_Tp>(poly){}
			constexpr Poly<_Tp> operator*(const NTT<_Tp> &it){
				Poly<_Tp> ret(Poly<_Tp>::n+it.length()-1);
				uint x(Poly<_Tp>::to_up(ret.length()));
				Poly<_Tp>::ReInit(x);
				NTT_transform(f,x,1);
				for(uint i(0);i<x;++i) f[i]*=f[i];
				NTT_transform(f,x,-1);
				return ret;
			}
		};
		template<typename _Tp>
		uint NTT<_Tp>::f[max_len];
	}
	/**
	 * 字符串的工具
	 */
	namespace String_Tools{
		namespace SA{
			template<int M=128,int N>
			void calc_sa(char (&str)[N],int sa[],int rk[],int n){
				int m=M-1;
				static int cnt[N<M?M:N],id[N],oldrk[N<<1],key[N];
				for(int i=1;i<=n;++i) ++cnt[rk[i]=str[i]];
				for(int i=1;i<=m;++i) cnt[i]+=cnt[i-1];
				for(int i=n;i;--i) sa[cnt[rk[i]]--]=i;
				for(int k=1,p;;k<<=1,m=p){
					p=0;
					for(int i=n;i>n-k;--i) id[++p]=i;
					for(int i=1;i<=n;++i) if(sa[i]>k) id[++p]=sa[i]-k;
					memset(cnt,0,sizeof(int)*(m+1));
					for(int i=1;i<=n;++i) ++cnt[key[i]=rk[id[i]]];
					for(int i=1;i<=m;++i) cnt[i]+=cnt[i-1];
					for(int i=n;i;--i) sa[cnt[key[i]]--]=id[i];
					memcpy(oldrk,rk,sizeof(int)*(n+1));
					p=0;
					for(int i=1;i<=n;++i){
						static auto cmp=[&k](int x,int y){
							return oldrk[x]==oldrk[y]&&oldrk[x+k]==oldrk[y+k];
						};
						rk[sa[i]]=cmp(sa[i],sa[i-1])?p:++p;
					}
					if(p==n) return;
				}
			}
			template<int N>
			constexpr void calc_height(char (&str)[N],int sa[],int rk[],int height[],int n){
				for(int i=1,k=0;i<=n;++i){
					if(!rk[i]) continue;
					k&&--k;
					for(;str[i+k]==str[sa[rk[i]-1]+k];++k);
					height[rk[i]]=k;
				}
			}
		}
	}
	/**
	 * 占坑
	 */
	namespace Data_Structure{}
	namespace Algorithm{
		using Base_Tools::swap;
		template<typename _Tp>
		void radix_sort(_Tp *x,int n,typename std::enable_if<std::is_integral<_Tp>::value,void>::type* =nullptr){
			static const int mask=(1<<8)-1;
			static int *cnt=new int[mask+1],*y=new int[n+5];
			for(int k=0;k<32;k+=8){
				for(int i=0;i<=mask;++i) cnt[i]=0;
				for(int i=1;i<=n;++i) ++cnt[(x[i]>>k)&mask];
				for(int sum=0,i=0;i<=mask;++i)
					sum+=cnt[i],cnt[i]=sum-cnt[i];
				for(int i=1;i<=n;++i) y[++cnt[(x[i]>>k)&mask]]=x[i];
				swap(x,y);
			}
		}
		template<typename _Tp,typename _Turn>
		void radix_sort(_Tp *x,int n,_Turn turn){
			static const int mask=(1<<8)-1;
			static int *cnt=new int[mask+1],*y=new int[n+5];
			for(int k=0;k<32;k+=8){
				for(int i=0;i<=mask;++i) cnt[i]=0;
				for(int i=1;i<=n;++i) ++cnt[(turn(x[i])>>k)&mask];
				for(int sum=0,i=0;i<=mask;++i)
					sum+=cnt[i],cnt[i]=sum-cnt[i];
				for(int i=1;i<=n;++i) y[++cnt[(turn(x[i])>>k)&mask]]=x[i];
				swap(x,y);
			}
		}
		template<typename _Tp>
		void radix_sort(_Tp *x,int n,int (*turn)(_Tp)){
			static const int mask=(1<<8)-1;
			static int *cnt=new int[mask+1],*y=new int[n+5];
			for(int k=0;k<32;k+=8){
				for(int i=0;i<=mask;++i) cnt[i]=0;
				for(int i=1;i<=n;++i) ++cnt[(turn(x[i])>>k)&mask];
				for(int sum=0,i=0;i<=mask;++i)
					sum+=cnt[i],cnt[i]=sum-cnt[i];
				for(int i=1;i<=n;++i) y[++cnt[(turn(x[i])>>k)&mask]]=x[i];
				swap(x,y);
			}
		}
		template<typename _Iterator>
		constexpr void reverse(_Iterator _st,_Iterator _ed){
			--_ed;
			for(;_st!=_ed;++_st,--_ed) swap(_st,_ed);
		}
	}
}
namespace MAIN{
	using namespace QL;
	using IO::lq;
	using Base_Tools::max;
	using Base_Tools::chkmax;
	constexpr int N=2.5e5+5,Node=5e5+5,Length=1e6+5;
	template<int NODE,int EDGE,typename _Tp=int>
	class Max_Flow{
	private:
		struct edge{
			int ver,nxt;
			_Tp flow;
			edge():ver(0),nxt(-1),flow(0){}
			edge(int Ver,int Nxt,_Tp Flow):ver(Ver),nxt(Nxt),flow(Flow){}
		};
		edge E[EDGE<<1];
		int head[NODE],tot,cur[NODE];
		_Tp dis[NODE];
		_Tp max_flow;
	public:
		Max_Flow():tot(-1){memset(head,-1,sizeof head);}
		void clear(){memset(head,-1,sizeof head),tot=-1;}
		int add(int u,int v,_Tp flow,_Tp back=0){
			E[++tot]=edge(v,head[u],flow),head[u]=tot;
			E[++tot]=edge(u,head[v],back),head[v]=tot;
			return tot;
		}
		edge &operator[](const int &x){return E[x];}
		int &operator()(const int &x){return head[x];}
		int edge_size()const{return tot;}
	private:
		bool bfs(const int &_s,const int &_t){
			memset(dis,0,sizeof dis);
			memcpy(cur,head,sizeof cur);
			static int q[NODE],l,r;
			dis[q[l=r=0]=_s]=1;
			for(int u,v,i;l<=r;)
				for(i=head[u=q[l++]];~i;i=E[i].nxt)
					if(E[i].flow&&!dis[v=E[i].ver])
						dis[q[++r]=v]=dis[u]+1;
			return dis[_t];
		}
		_Tp dinic(int u,const int &_t,_Tp flow){
			if(u==_t) return flow;
			_Tp rest=flow,k;
			for(int &i=cur[u],v;(~i)&&rest;i=E[i].nxt){
				if(E[i].flow&&dis[v=E[i].ver]==dis[u]+1){
					if(k=dinic(v,_t,std::min(E[i].flow,rest)),k)
						E[i].flow-=k,E[i^1].flow+=k,rest-=k;
					else dis[v]=-114514;
				}
			}
			return flow-rest;
		}
	public:
		_Tp work(const int &_s,const int &_t){
			max_flow=0;
			static _Tp Inf;
			__builtin_memset(&Inf,0x3f,sizeof Inf);
			for(_Tp flow;bfs(_s,_t);)
				while(flow=dinic(_s,_t,Inf),flow) max_flow+=flow;
			return max_flow;
		}
		_Tp work(const int &_s,const int &_t,int Inf){
			max_flow=0;
			for(_Tp flow;Inf&&bfs(_s,_t);)
				while(flow=dinic(_s,_t,Inf),flow) max_flow+=flow,Inf-=flow;
			return max_flow;
		}
	};
	int n,tot;
	Max_Flow<Length,Length,int> Lyh;
	std::array<int,N> u,d;
	std::array<std::vector<int>,Length> G;
	std::array<std::vector<std::pair<int,int>>,Length> r,cu,cd;
	std::array<bool,Node> visited;
	int cnt;
	void dfs(int u){
		if(visited[u]) return;
		++cnt;
		visited[u]=true;
		for(int v:G[u]) dfs(v);
	}
	std::array<int,Length> lg;
	std::array<std::array<int,Length>,17> ST[2];
	std::array<int,Length> vis;
	int tit;
	std::array<int,Length> match;
	bool rush(int u){
		for(int v:G[u]){
			if(vis[v]==tit) continue;
			vis[v]=tit;
			if(match[v]==-1||rush(match[v])){
				match[v]=u;
				return true;
			}
		}
		return false;
	}
	signed _main_(){
		static auto build_st=[](const auto &h,auto &st){
			for(int i=1;i<=n;++i) st[0][i]=h[i];
			for(int k=1;k<17;++k)
				for(int i=1;i+(1<<k)-1<=n;++i)
					st[k][i]=max(st[k-1][i],st[k-1][i+(1<<(k-1))]);
		};
		do{
			lq.read(n);
			int mu=0,md=0;
			for(int i=1;i<=n;++i)
				lq.read(u[i],d[i]),chkmax(mu,u[i]),chkmax(md,d[i]);
		}while(false);
		build_st(u,ST[0]);
		build_st(d,ST[1]);
		for(int i=2;i<=n;++i) lg[i]=lg[i>>1]+1;
		do{
			int lu=u[1];
			for(int i=2;i<=n;++i){
				if(lu!=u[i]){
					++tot;
					cu[lu].emplace_back(tot,lu<u[i]);
					r[i-1].emplace_back(tot,0);
					// lq.writeln("u: ",i,"(",lu<u[i],") ",tot);
				}
				lu=u[i];
			}
		}while(false);
		do{
			int ld=d[1];
			for(int i=2;i<=n;++i){
				if(ld!=d[i]){
					++tot;
					cd[ld].emplace_back(tot,ld<d[i]);
					r[i-1].emplace_back(tot,0);
					// lq.writeln("d: ",i,"(",ld<d[i],") ",tot);
				}
				ld=d[i];
			}
		}while(false);
		static auto qry=[](const auto &st,int l,int r){
			int k=lg[r-l+1];
			return max(st[k][l],st[k][r-(1<<k)+1]);
		};
		static auto q1=[](int l,int r){return qry(ST[0],l,r);};
		static auto q2=[](int l,int r){return qry(ST[1],l,r);};
		static auto q3=[](int l,int r){return Inf;};
		int s=0,t=tot+1;
		static auto work=[](const auto &r,const auto &q){
			int h=0;
			for(const auto &v:r){
				if(v.empty()) continue;
				auto itr=v.begin()+1;
				for(;itr!=v.end();++itr){
					if(q((itr-1)->first,itr->first)>h){
						G[(itr-1)->first].emplace_back(itr->first);
						G[itr->first].emplace_back((itr-1)->first);
					}
				}
				++h;
			}
		};
		work(cu,q1),work(cd,q2),work(r,q3);
		int ans=tot*2;
		for(int i=1;i<=tot;++i) match[i]=-1;
		for(int i=1;i<=tot;++i){
			vis[i]=++tit,ans-=rush(i);
		}
		// int ans=tot;
		// for(int i=1;i<=tot;++i)
		// 	cnt=0,dfs(i),ans-=cnt>>1;
		lq.write(ans/2);
		return 0;
	}
}
signed main(){
	return MAIN::_main_();
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 17ms
memory: 146288kb

input:

8
1 4
4 2
3 2
5 1
6 4
4 2
2 3
5 1

output:

7

result:

ok single line: '7'

Test #2:

score: 0
Accepted
time: 21ms
memory: 142128kb

input:

5
23 15
23 17
3 22
15 3
5 1

output:

4

result:

ok single line: '4'

Test #3:

score: 0
Accepted
time: 15ms
memory: 146292kb

input:

8
1 2
2 2
2 1
1 1
1 2
2 2
2 2
1 2

output:

4

result:

ok single line: '4'

Test #4:

score: 0
Accepted
time: 15ms
memory: 138088kb

input:

2
1 1000000
1000000 1

output:

1

result:

ok single line: '1'

Test #5:

score: 0
Accepted
time: 20ms
memory: 133908kb

input:

1
1 1

output:

0

result:

ok single line: '0'

Test #6:

score: 0
Accepted
time: 14ms
memory: 170860kb

input:

1000
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1...

output:

0

result:

ok single line: '0'

Test #7:

score: -100
Wrong Answer
time: 20ms
memory: 172976kb

input:

1000
2 1
2 1
1 2
1 2
1 2
1 2
2 2
1 1
1 2
1 2
1 1
1 2
2 1
1 1
1 2
2 2
1 1
2 2
1 2
1 2
2 1
2 1
1 2
1 1
1 2
2 2
2 1
2 2
1 2
2 1
1 2
1 2
2 2
1 2
1 2
2 2
2 1
2 1
2 1
1 2
2 1
2 2
1 1
1 2
2 2
2 1
1 1
1 1
2 1
2 2
2 2
1 1
1 1
1 1
1 1
2 1
2 2
1 2
2 1
2 2
1 1
2 2
2 1
2 1
1 1
2 1
2 1
2 1
1 2
1 1
2 1
2 1
2 1
2 2...

output:

512

result:

wrong answer 1st lines differ - expected: '505', found: '512'