------------------------------- __int128_t ------ ------------------------------- __uint128_t ------ ------------------------------- optimize ------ #pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #pragma GCC optimize("inline") ------------------------------- stdc ------ #include ------------------------------- sys_time ------ #include ------------------------------- namespace ------ using namespace std; ------------------------------- BoostMultiprecision ------ #include using namespace boost::multiprecision; ------------------------------- define_MD ------ #define MD (1000000007U) ------------------------------- define_for_Mint ------ #define MINT_W (32U) #define MINT_R (294967268U) #define MINT_RR (582344008U) #define MINT_MDNINV (2226617417U) ------------------------------- define_MD_PRIMITIVE_ROOT ------ #define MD_PRIMITIVE_ROOT (5U) ------------------------------- define_PI ------ #define PI 3.14159265358979323846 ------------------------------- cLtraits_identity ------ template struct cLtraits_identity { using type = T; }; ------------------------------- cLtraits_try_make_signed ------ template using cLtraits_try_make_signed = typename conditional< is_integral::value, make_signed, cLtraits_identity >::type; ------------------------------- cLtraits_try_make_unsigned ------ template using cLtraits_try_make_unsigned = typename conditional< is_integral::value, make_unsigned, cLtraits_identity >::type; ------------------------------- cLtraits_common_type ------ template struct cLtraits_common_type { using tS = typename cLtraits_try_make_signed::type; using tT = typename cLtraits_try_make_signed::type; using type = typename common_type::type; }; ------------------------------- workmemory ------ inplace_L void *wmem; char memarr[96000000]; ------------------------------- workmemory_init ------ wmem = memarr; ------------------------------- min_L ------ template inline auto min_L(S a, T b) -> typename cLtraits_common_type::type { return (typename cLtraits_common_type::type) a <= (typename cLtraits_common_type::type) b ? a : b; } ------------------------------- max_L ------ template inline auto max_L(S a, T b) -> typename cLtraits_common_type::type { return (typename cLtraits_common_type::type) a >= (typename cLtraits_common_type::type) b ? a : b; } ------------------------------- chmin ------ template inline S chmin(S &a, T b){if(a>b)a=b;return a;} ------------------------------- chmax ------ template inline S chmax(S &a, T b){if(a T inline fDiv(T a, S b){ T m; if(b < 0) a = -a, b = -b; m = a % b; if(m == 0) return a / b; if(m < 0) m += b; return (a - m) / b; } ------------------------------- cDiv ------ template T inline cDiv(T a, S b){ T m; if(b < 0) a = -a, b = -b; m = a % b; if(m == 0) return a / b; if(m < 0) m += b; return (a + b - m) / b; } ------------------------------- divup ------ template inline S divup_L(S a, T b){ return (a+b-1)/b; } ------------------------------- moddw ------ template inline S moddw_L(S a, const T b){ a %= b; if(a < 0) a += b; return a; } ------------------------------- walloc1d ------ template inline void walloc1d(T **arr, int x, void **mem = &wmem){ static int skip[16] = {0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; (*mem) = (void*)( ((char*)(*mem)) + skip[((ull)(*mem)) & 15] ); (*arr)=(T*)(*mem); (*mem)=((*arr)+x); } template inline void walloc1d(T **arr, int x1, int x2, void **mem = &wmem){ walloc1d(arr, x2-x1, mem); (*arr) -= x1; } ------------------------------- walloc2d ------ template inline void walloc2d(T ***arr, int x, int y, void **mem = &wmem){ int i; walloc1d(arr, x, mem); rep(i,x) walloc1d(&((*arr)[i]), y, mem); } template inline void walloc2d(T ***arr, int x1, int x2, int y1, int y2, void **mem = &wmem){ int i; walloc1d(arr, x1, x2, mem); rep(i,x1,x2) walloc1d(&((*arr)[i]), y1, y2, mem); } ------------------------------- malloc1d ------ template void malloc1d(T **arr, int x){ (*arr) = (T*)malloc(x*sizeof(T)); } ------------------------------- free1d ------ template void free1d(T *arr){ free(arr); } ------------------------------- malloc2d ------ template void malloc2d(T ***arr, int x, int y){ int i; (*arr) = (T**)malloc(x*sizeof(T*)); (*arr)[0] = (T*)malloc(x*y*sizeof(T)); REP(i,1,x)(*arr)[i]=(*arr)[i-1]+y; } ------------------------------- free2d ------ template void free2d(T **arr){ free(arr[0]); free(arr); } ------------------------------- isPrime_head ------ #define ISPRIME_PRE_CALC_SIZE 1000000 char isPrime_prime_table[ISPRIME_PRE_CALC_SIZE]; template inline int isPrime(T n); void isPrime32_init(void); int isPrime32_sub(int b, unsigned n); int isPrime32(unsigned n); int isPrime64_sub(ll b, ull n); int isPrime64(ull n); ------------------------------- isPrime_init ------ { isPrime32_init(); } ------------------------------- isPrime ------ template inline int isPrime(T n){ T i; if(n<=1) return 0; if(n <= (1ULL<<32) - 1) return isPrime32(n); if(n <= (1ULL<<63) - 1 + (1ULL<<63)) return isPrime64(n); if(n<=3) return 1; if(n%2==0) return 0; for(i=3;i*i<=n;i+=2) if(n%i==0) return 0; return 1; } int isPrime32_sub(int b, unsigned n){ unsigned i, t = 0, u = n-1; ull nw, nx; while(!(u&1)) t++, u >>= 1; nw = 1; nx = b % n; while(u){ if(u&1) nw = (nw * nx) % n; nx = (nx * nx) % n; u >>= 1; } rep(i,t){ nx = (nw * nw) % n; if(nx == 1 && nw != 1 && nw != n-1) return 0; nw = nx; } if(nw == 1) return 1; return 0; } int isPrime32(unsigned n){ if(n < 1d5) return isPrime_prime_table[n]; if(n % 2 == 0) return 0; if(!isPrime32_sub(2,n)) return 0; if(n<=1000000){ if(!isPrime32_sub(3,n)) return 0; } else { if(!isPrime32_sub(7,n)) return 0; if(!isPrime32_sub(61,n)) return 0; } return 1; } int isPrime64_sub(ll b, ull n){ ull i, t = 0, u = n-1; __uint128_t nw, nx; while(!(u&1)) t++, u >>= 1; nw = 1; nx = b % n; while(u){ if(u&1) nw = (nw * nx) % n; nx = (nx * nx) % n; u >>= 1; } rep(i,t){ nx = (nw * nw) % n; if(nx == 1 && nw != 1 && nw != n-1) return 0; nw = nx; } if(nw == 1) return 1; return 0; } int isPrime64(ull n){ if(n < 1d5) return isPrime_prime_table[n]; if(n < (1ULL<<32)) return isPrime32(n); if(n % 2 == 0) return 0; if(!isPrime64_sub(2,n)) return 0; if(n <= 21652684502221ULL){ if(!isPrime64_sub(1215,n)) return 0; if(!isPrime64_sub(34862,n)) return 0; if(!isPrime64_sub(574237825,n)) return 0; } else { if(!isPrime64_sub(325,n)) return 0; if(!isPrime64_sub(9375,n)) return 0; if(!isPrime64_sub(28178,n)) return 0; if(!isPrime64_sub(450775,n)) return 0; if(!isPrime64_sub(9780504,n)) return 0; if(!isPrime64_sub(1795265022,n)) return 0; } return 1; } void isPrime32_init(void){ int i, j, k; k = Isqrt_f(ISPRIME_PRE_CALC_SIZE); rep(i,2,ISPRIME_PRE_CALC_SIZE) isPrime_prime_table[i] = 1; rep(i,2,k+1) if(isPrime_prime_table[i]) rep(j,i*i,ISPRIME_PRE_CALC_SIZE,i) isPrime_prime_table[j] = 0; } ------------------------------- Factor_head ------ #define FACTOR_PRE_CALC_SIZE 1000000 int factor_hasprime_table[FACTOR_PRE_CALC_SIZE]; template int Factor(T N, R1 fac[], R2 fs[], void *mem = wmem); template int Factor(T N, R1 fac[], void *mem = wmem); template int Factor(T N, void *mem = wmem); unsigned Factor32_rho(unsigned n); template int Factor32(unsigned N, R1 fac[], R2 fs[], void *mem = wmem); ull Factor64_rho(ull n); template int Factor64(ull N, R1 fac[], R2 fs[], void *mem = wmem); void Factor32_init(void); ------------------------------- Factor_init ------ { Factor32_init(); } ------------------------------- Factor ------ template int Factor(T N, R1 fac[], R2 fs[], void *mem/* = wmem*/){ T i; int sz = 0; if(N <= 1) return sz; if(N <= (1ULL<<32) - 1) return Factor32(N, fac, fs, mem); if(N <= (1ULL<<63) - 1 + (1ULL<<63)) return Factor64(N, fac, fs, mem); if(N%2==0){ fac[sz] = 2; fs[sz] = 1; N /= 2; while(N%2==0){ N /= 2; fs[sz]++; } sz++; } for(i=3;i*i<=N;i+=2) if(N%i==0){ fac[sz] = i; fs[sz] = 1; N /= i; while(N%i==0){ N /= i; fs[sz]++; } sz++; } if(N > 1){ fac[sz] = N; fs[sz] = 1; sz++; } return sz; } template int Factor(T N, R1 fac[], void *mem/* = wmem*/){ int *fs; walloc1d(&fs,128,&mem); return Factor(N, fac, fs, mem); } template int Factor(T N, void *mem/* = wmem*/){ T *fac; int *fs; walloc1d(&fac,128,&mem); walloc1d(&fs,128,&mem); return Factor(N, fac, fs, mem); } unsigned Factor32_rho(unsigned n){ static Rand rnd; const int step = 16; int i, s, nx, mx; ull x, y, memo, c, m; unsigned g; ll lm; lm = min(1ULL<<30, n - 1); for(;;){ x = y = rnd.get(1LL, lm); c = rnd.get(1LL, lm); g = 1; for(nx=1;g==1;nx<<=1){ x = y; rep(i,nx) y = (y * y + c) % n; for(s=0;s= y) m = (m * (x - y)) % n; else m = (m * (y - x)) % n; } g = gcd(n, m); if(g != 1){ if(g != n) return g; y = memo; for(;;){ y = (y * y + c) % n; if(x >= y) m = x - y; else m = y - x; g = gcd(n, m); if(g == n) break; if(g != 1) return g; } } } } } return 0; } template int Factor32(unsigned N, R1 fac[], R2 fs[], void *mem/* = wmem*/){ int res = 0, sz = 0, i, k; unsigned *val, *valtmp, pf, n; if(N <= 1) return 0; walloc1d(&val, 128, &mem); walloc1d(&valtmp, 128, &mem); while(N%2==0) val[res++] = 2, N /= 2; while(N%3==0) val[res++] = 3, N /= 3; while(N%5==0) val[res++] = 5, N /= 5; if(N > 1){ valtmp[sz++] = N; } while(sz){ while(sz && isPrime32(valtmp[sz-1])){ val[res] = valtmp[sz-1]; res++; sz--; } if(sz==0) break; n = valtmp[sz-1]; if(n < FACTOR_PRE_CALC_SIZE){ while(n > 1){ val[res++] = factor_hasprime_table[n]; n /= factor_hasprime_table[n]; } sz--; } else { pf = Factor32_rho(n); valtmp[sz-1] = pf; valtmp[sz] = n / pf; sz++; } } sortA(res, val, mem); k = 0; rep(i,res){ if(k && fac[k-1] == val[i]) fs[k-1]++, continue; fac[k] = val[i]; fs[k] = 1; k++; } res = k; return res; } ull Factor64_rho(ull n){ static Rand rnd; const int step = 16; int i, s, nx, mx; __uint128_t x, y, memo, c, m; ull g; ll lm; lm = min(1ULL<<30, n - 1); for(;;){ x = y = rnd.get(1LL, lm); c = rnd.get(1LL, lm); g = 1; for(nx=1;g==1;nx<<=1){ x = y; rep(i,nx) y = (y * y + c) % n; for(s=0;s= y) m = (m * (x - y)) % n; else m = (m * (y - x)) % n; } g = gcd(n, m); if(g != 1){ if(g != n) return g; y = memo; for(;;){ y = (y * y + c) % n; if(x >= y) m = x - y; else m = y - x; g = gcd(n, m); if(g == n) break; if(g != 1) return g; } } } } } return 0; } template int Factor64(ull N, R1 fac[], R2 fs[], void *mem/* = wmem*/){ int res = 0, sz = 0, i, k; ull *val, *valtmp, pf, n; if(N <= 1) return 0; walloc1d(&val, 128, &mem); walloc1d(&valtmp, 128, &mem); while(N%2==0) val[res++] = 2, N /= 2; while(N%3==0) val[res++] = 3, N /= 3; while(N%5==0) val[res++] = 5, N /= 5; if(N > 1){ valtmp[sz++] = N; } while(sz){ while(sz && isPrime64(valtmp[sz-1])){ val[res] = valtmp[sz-1]; res++; sz--; } if(sz==0) break; n = valtmp[sz-1]; if(n < FACTOR_PRE_CALC_SIZE){ while(n > 1){ val[res++] = factor_hasprime_table[n]; n /= factor_hasprime_table[n]; } sz--; } else if(n < (1ULL<<32)){ pf = Factor32_rho(n); valtmp[sz-1] = pf; valtmp[sz] = n / pf; sz++; } else { pf = Factor64_rho(n); valtmp[sz-1] = pf; valtmp[sz] = n / pf; sz++; } } sortA(res, val, mem); k = 0; rep(i,res){ if(k && fac[k-1] == val[i]) fs[k-1]++, continue; fac[k] = val[i]; fs[k] = 1; k++; } res = k; return res; } void Factor32_init(void){ int i, j, k; k = Isqrt_f(FACTOR_PRE_CALC_SIZE); rep(i,2,FACTOR_PRE_CALC_SIZE) factor_hasprime_table[i] = i; rep(i,2,k+1) if(factor_hasprime_table[i]==i) rep(j,i*i,FACTOR_PRE_CALC_SIZE,i) factor_hasprime_table[j] = i; } ------------------------------- FactorM_head ------ template int FactorM(T N, R fac[], void *mem = wmem); template int FactorM(T N, void *mem = wmem); ------------------------------- FactorM ------ template int FactorM(T N, R fac[], void *mem/* = wmem*/){ int i, j, msz, sz = 0; T *mfac; int *fs; walloc1d(&mfac,128,&mem); walloc1d(&fs,128,&mem); msz = Factor(N, mfac, fs, mem); rep(i,msz) rep(j,fs[i]) fac[sz++] = mfac[i]; return sz; } template int FactorM(T N, void *mem/* = wmem*/){ int i, msz, res = 0; T *mfac; int *fs; walloc1d(&mfac,128,&mem); walloc1d(&fs,128,&mem); msz = Factor(N, mfac, fs, mem); rep(i,msz) res += fs[i]; return res; } ------------------------------- Divisor_head ------ template int Divisor(T N, R res[], void *mem = wmem); ------------------------------- Divisor ------ template int Divisor(T N, R res[], void *mem/* = wmem*/){ int i, j, k, s, sz = 0; T *fc; int *fs, fsz; walloc1d(&fc, 128, &mem); walloc1d(&fs, 128, &mem); fsz = Factor(N, fc, fs, mem); res[sz++] = 1; rep(i,fsz){ s = sz; k = s * fs[i]; rep(j,k) res[sz++] = res[j] * fc[i]; } sort(res, res+sz); return sz; } ------------------------------- DivisorSum_head ------ ll DivisorSum(ll n, void *mem = wmem); ------------------------------- DivisorSum ------ ll DivisorSum(ll n, void *mem/* = wmem*/){ int i; ll res, t, s; int fs, *fn; ll *fc; if(n<=0) return 0; walloc1d(&fc, 128, &mem); walloc1d(&fn, 128, &mem); fs = Factor(n, fc, fn, mem); res = 1; rep(i,fs){ s = t = 1; rep(j,fn[i]){ t *= fc[i]; s += t; } res *= s; } return res; } ------------------------------- Moebius_head ------ template int Moebius(T n, void *mem = wmem); ------------------------------- Moebius ------ template int Moebius(T n, void *mem /* = wmem*/){ int i; T *fc; int *fs, fsz; walloc1d(&fc, 128, &mem); walloc1d(&fs, 128, &mem); fsz = Factor(n, fc, fs, mem); rep(i,fsz) if(fs[i] > 1) return 0; if(fsz%2) return -1; return 1; } ------------------------------- EulerPhi_head ------ template T EulerPhi(T n, void *mem = wmem); ------------------------------- EulerPhi ------ template T EulerPhi(T n, void *mem /* = wmem*/){ int i; T *fc; int *fs, fsz; walloc1d(&fc, 128, &mem); walloc1d(&fs, 128, &mem); fsz = Factor(n, fc, fs, mem); rep(i,fsz) n = n / fc[i] * (fc[i]-1); return n; } ------------------------------- Ilog2_f ------ inline int Ilog2_f_L(const int n){ int res; if(n <= 0) return -1; res = sizeof(int) * 8 - __builtin_clz(n) - 1; return res; } inline int Ilog2_f_L(const ll n){ int res; if(n <= 0) return -1; res = sizeof(ll) * 8 - __builtin_clzll(n) - 1; return res; } ------------------------------- Ilog2_c ------ inline int Ilog2_c_L(const int n){ int res; if(n <= 0) return -1; res = sizeof(int) * 8 - __builtin_clz(n) - 1; if(n != (1< void sortI(int N, T1 a[], void *mem = wmem){ sort(a, a+N); } template void sortI(int N, T1 a[], T2 b[], void *mem = wmem){ int i; pair *arr; walloc1d(&arr, N, &mem); rep(i,N) arr[i].first = a[i], arr[i].second = b[i]; sort(arr, arr+N); rep(i,N) a[i] = arr[i].first, b[i] = arr[i].second; } template void sortI(int N, T1 a[], T2 b[], T3 c[], void *mem = wmem){ int i; pair > *arr; walloc1d(&arr, N, &mem); rep(i,N) arr[i].first = a[i], arr[i].second.first = b[i], arr[i].second.second = c[i]; sort(arr, arr+N); rep(i,N) a[i] = arr[i].first, b[i] = arr[i].second.first, c[i] = arr[i].second.second; } template void sortI(int N, T1 a[], T2 b[], T3 c[], T4 d[], void *mem = wmem){ int i; pair, pair > *arr; walloc1d(&arr, N, &mem); rep(i,N) arr[i].first.first = a[i], arr[i].first.second = b[i], arr[i].second.first = c[i], arr[i].second.second = d[i]; sort(arr, arr+N); rep(i,N) a[i] = arr[i].first.first, b[i] = arr[i].first.second, c[i] = arr[i].second.first, d[i] = arr[i].second.second; } ------------------------------- sortA ------ template inline int sort_helper_getbit(T A[]){ return -1; } template<> inline int sort_helper_getbit(int A[]){ return sizeof(int)*8; } template<> inline int sort_helper_getbit(unsigned A[]){ return sizeof(unsigned)*8; } template<> inline int sort_helper_getbit(ll A[]){ return sizeof(ll)*8; } template<> inline int sort_helper_getbit(ull A[]){ return sizeof(ull)*8; } template<> inline int sort_helper_getbit(char A[]){ return sizeof(char)*8; } template void sortA_1_int_L(int N, T A[], void *mem = wmem){ int i, j, k, b, s, ok; ok = 1; rep(i,1,N) if(A[i-1] > A[i]){ ok = 0; break; } if(ok) return; if(N < 128){ sort(A,A+N); return; } b = sort_helper_getbit(A); if(b==-1){ sort(A,A+N); return; } T mn, mx; mn = mx = A[0]; rep(i,1,N) mn ?= A[i]; ok = 1; if(mn < 0 && mx > 0 && (mn < -N || mx > N)) ok = 0; if(ok && mx - mn > N) ok = 0; if(ok){ int *tmp; walloc1d(&tmp, mx-mn+1, &mem); rep(i,mx-mn+1) tmp[i] = 0; rep(i,N) tmp[A[i]-mn]++; k = 0; rep(i,mx-mn+1) while(tmp[i] > 0){ tmp[i]--; A[k++] = i+mn; } return; } { typename make_unsigned::type *t[2], mask, cur, one = 1; T tone = 1; int *pos, nn = 0, ss; s = Ilog2_f(N); if(s > 8) s = (8 + (s-7)/2); ss = 1; for(;;){ if(ss >= b) break; if( mx >= 0 && (tone << (ss-1)) < mx ) ss++, continue; if( mn < 0 && -(tone << (ss-1)) >= mn ) ss++, continue; break; } k = ss /+ s; s = ss /+ k; mask = 0; rep(i,b) if(i < s*k) mask |= one << i; t[0] = (typename make_unsigned::type *) A; walloc1d(&t[1], N, &mem); walloc1d(&pos, (1<>(s*j))+1]++; rep(i,(1<>(s*j)]++] = t[nn][i]; nn ^= 1; mask ^= cur; } if(mn < 0 && mx >= 0){ k = 0; rep(i,N) if(A[i] < 0) k++; rep(i,k) t[nn^1][i] = t[nn][N-k+i]; rep(i,k,N) t[nn^1][i] = t[nn][i-k]; nn ^= 1; } if(nn==1){ rep(i,N) t[0][i] = t[1][i]; } return; } sort(A, A+N); } template void sortA_1_nonint_L(int N, T A[], void *mem = wmem){ sort(A,A+N); } template void sortA_1_call_L(int N, T A[], void *mem = wmem){ sortA_1_nonint_L(N, A, mem); } template<> void sortA_1_call_L(int N, int A[], void *mem){ sortA_1_int_L(N, A, mem); } template<> void sortA_1_call_L(int N, unsigned A[], void *mem){ sortA_1_int_L(N, A, mem); } template<> void sortA_1_call_L(int N, ll A[], void *mem){ sortA_1_int_L(N, A, mem); } template<> void sortA_1_call_L(int N, ull A[], void *mem){ sortA_1_int_L(N, A, mem); } template<> void sortA_1_call_L(int N, char A[], void *mem){ sortA_1_int_L(N, A, mem); } template void sortA(int N, T1 a[], void *mem = wmem){ sortA_1_call_L(N, a, mem); } template void sortA_2_int_L(int N, T1 A[], T2 B[], void *mem = wmem){ int b_a, b_b, s1, s2, so2; T1 mn1, mx1; T2 mn2, mx2; typename cLtraits_try_make_unsigned::type r1; typename cLtraits_try_make_unsigned::type r2; so2 = 1; rep(i,1,N){ if(A[i-1] > A[i] || (A[i-1]==A[i] && B[i-1] > B[i])){ so2 = 0; break; } } if(so2) return; so2 = 1; rep(i,1,N){ if(A[i-1] > A[i]){ so2 = 0; break; } } if(so2==1){ int k = 0; rep(i,1,N) if(A[i] != A[i-1]){ sortA_1_call_L(i-k, B+k, mem); k = i; } sortA_1_call_L(N-k, B+k, mem); return; } if(N < 128){ sortI(N,A,B,mem); return; } b_a = sort_helper_getbit(A); b_b = sort_helper_getbit(B); if(b_a == -1 || b_b == -1){ sortI(N,A,B,mem); return; } mn1 = mx1 = A[0]; rep(i,1,N) mn1 ?= A[i]; mn2 = mx2 = B[0]; rep(i,1,N) mn2 ?= B[i]; if(mn1 < -ll_inf || mn2 < -ll_inf || mx1 > ll_inf || mx2 > ll_inf || mx1-mn1 > ll_inf || mx2-mn2 > ll_inf){ sortI(N,A,B,mem); return; } r1 = (typename cLtraits_try_make_unsigned::type)(mx1) - (typename cLtraits_try_make_unsigned::type)(mn1); r2 = (typename cLtraits_try_make_unsigned::type)(mx2) - (typename cLtraits_try_make_unsigned::type)(mn2); if(r1 == 0){ sortA_1_call_L(N, B, mem); return; } if(r2 == 0){ sortA_1_call_L(N, A, mem); return; } if(r1 <= N){ so2 = 1; rep(i,1,N) if(B[i-1] > B[i]){ so2 = 0; break; } if(so2 == 1){ T1 *aa; T2 *bb; int *pos, k; walloc1d(&aa,N,&mem); walloc1d(&bb,N,&mem); walloc1d(&pos,r1+2,&mem); rep(i,r1+2) pos[i] = 0; rep(i,N) aa[i] = A[i]; rep(i,N) bb[i] = B[i]; rep(i,N) pos[(typename cLtraits_try_make_unsigned::type)((typename cLtraits_try_make_unsigned::type)aa[i]-(typename cLtraits_try_make_unsigned::type)mn1)+1]++; rep(i,1,r1+2) pos[i] += pos[i-1]; rep(i,N){ k = pos[(typename cLtraits_try_make_unsigned::type)((typename cLtraits_try_make_unsigned::type)aa[i]-(typename cLtraits_try_make_unsigned::type)mn1)+0]++; A[k] = aa[i]; B[k] = bb[i]; } return; } } s1 = s2 = 1; while( s1 < 64 && r1 >= (1ULL<= (1ULL<> s2)) + ((int)mn1); B[i] = ((int)(tmp[i] & ((1U<> s2)) + ((ll)mn1); B[i] = ((ll)(tmp[i] & ((1ULL< void sortA_2_nonint_L(int N, T1 A[], T2 B[], void *mem = wmem){ sortI(N,A,B,mem); } template void sortA_2_call_L(int N, T1 A[], T2 B[], void *mem = wmem){ sortA_2_nonint_L(N, A, B, mem); } template void sortA_2_call_L(int N, int A[], T2 B[], void *mem){ sortA_2_int_L(N, A, B, mem); } template void sortA_2_call_L(int N, unsigned A[], T2 B[], void *mem){ sortA_2_int_L(N, A, B, mem); } template void sortA_2_call_L(int N, ll A[], T2 B[], void *mem){ sortA_2_int_L(N, A, B, mem); } template void sortA_2_call_L(int N, ull A[], T2 B[], void *mem){ sortA_2_int_L(N, A, B, mem); } template void sortA_2_call_L(int N, char A[], T2 B[], void *mem){ sortA_2_int_L(N, A, B, mem); } template void sortA(int N, T1 a[], T2 b[], void *mem = wmem){ sortA_2_call_L(N, a, b, mem); } template void sortA(int N, T1 a[], T2 b[], T3 c[], void *mem = wmem){ int i; pair > *arr; walloc1d(&arr, N, &mem); rep(i,N) arr[i].first = a[i], arr[i].second.first = b[i], arr[i].second.second = c[i]; sort(arr, arr+N); rep(i,N) a[i] = arr[i].first, b[i] = arr[i].second.first, c[i] = arr[i].second.second; } template void sortA(int N, T1 a[], T2 b[], T3 c[], T4 d[], void *mem = wmem){ int i; pair, pair > *arr; walloc1d(&arr, N, &mem); rep(i,N) arr[i].first.first = a[i], arr[i].first.second = b[i], arr[i].second.first = c[i], arr[i].second.second = d[i]; sort(arr, arr+N); rep(i,N) a[i] = arr[i].first.first, b[i] = arr[i].first.second, c[i] = arr[i].second.first, d[i] = arr[i].second.second; } ------------------------------- rsortA ------ template void rsortA(int N, T1 a[], void *mem = wmem){ sortA(N, a, mem); reverse(a, a+N); } template void rsortA(int N, T1 a[], T2 b[], void *mem = wmem){ sortA(N, a, b, mem); reverse(a, a+N); reverse(b, b+N); } template void rsortA(int N, T1 a[], T2 b[], T3 c[], void *mem = wmem){ sortA(N, a, b, c, mem); reverse(a, a+N); reverse(b, b+N); reverse(c, c+N); } template void rsortA(int N, T1 a[], T2 b[], T3 c[], T4 d[], void *mem = wmem){ sortA(N, a, b, c, d, mem); reverse(a, a+N); reverse(b, b+N); reverse(c, c+N); reverse(d, d+N); } ------------------------------- sortA_index ------ template void sortA_index(int N, T1 a[], T2 b[], void *mem = wmem){ int i; rep(i,N) b[i] = i; sortA(N,a,b,mem); } template void sortA_index(int N, T1 a[], T2 b[], T3 c[], void *mem = wmem){ int i; rep(i,N) c[i] = i; sortA(N,a,b,c,mem); } template void sortA_index(int N, T1 a[], T2 b[], T3 c[], T4 d[], void *mem = wmem){ int i; rep(i,N) d[i] = i; sortA(N,a,b,c,d,mem); } ------------------------------- sortV ------ template void sortV(vector &a, void *mem = wmem){ int i, n = a.size(); T1 *aa; walloc1d(&aa, n, &mem); rep(i,n) aa[i] = a[i]; sortA(n, aa, mem); rep(i,n) a[i] = aa[i]; } template void sortV(vector &a, vector &b, void *mem = wmem){ int i, n = a.size(); T1 *aa; T2 *bb; walloc1d(&aa, n, &mem); walloc1d(&bb, n, &mem); rep(i,n) aa[i] = a[i]; rep(i,n) bb[i] = b[i]; sortA(n, aa, bb, mem); rep(i,n) a[i] = aa[i]; rep(i,n) b[i] = bb[i]; } template void sortV(vector &a, vector &b, vector &c, void *mem = wmem){ int i, n = a.size(); T1 *aa; T2 *bb; T3 *cc; walloc1d(&aa, n, &mem); walloc1d(&bb, n, &mem); walloc1d(&cc, n, &mem); rep(i,n) aa[i] = a[i]; rep(i,n) bb[i] = b[i]; rep(i,n) cc[i] = c[i]; sortA(n, aa, bb, cc, mem); rep(i,n) a[i] = aa[i]; rep(i,n) b[i] = bb[i]; rep(i,n) c[i] = cc[i]; } template void sortV(vector &a, vector &b, vector &c, vector &d, void *mem = wmem){ int i, n = a.size(); T1 *aa; T2 *bb; T3 *cc; T4 *dd; walloc1d(&aa, n, &mem); walloc1d(&bb, n, &mem); walloc1d(&cc, n, &mem); walloc1d(&dd, n, &mem); rep(i,n) aa[i] = a[i]; rep(i,n) bb[i] = b[i]; rep(i,n) cc[i] = c[i]; rep(i,n) dd[i] = d[i]; sortA(n, aa, bb, cc, dd, mem); rep(i,n) a[i] = aa[i]; rep(i,n) b[i] = bb[i]; rep(i,n) c[i] = cc[i]; rep(i,n) d[i] = dd[i]; } ------------------------------- rsortV ------ template void rsortV(vector &a, void *mem = wmem){ sortV(a, mem); reverse(a.begin(), a.end()); } template void rsortV(vector &a, vector &b, void *mem = wmem){ sortV(a, b, mem); reverse(a.begin(), a.end()); reverse(b.begin(), b.end()); } template void rsortV(vector &a, vector &b, vector &c, void *mem = wmem){ sortV(a, b, c, mem); reverse(a.begin(), a.end()); reverse(b.begin(), b.end()); reverse(c.begin(), c.end()); } template void rsortV(vector &a, vector &b, vector &c, vector &d, void *mem = wmem){ sortV(a, b, c, d, mem); reverse(a.begin(), a.end()); reverse(b.begin(), b.end()); reverse(c.begin(), c.end()); reverse(d.begin(), d.end()); } ------------------------------- sortF_unsigned ------ void sortF_L(int N, unsigned A[], void *mem = wmem){ int i, m, bt; unsigned *arr, c; int *sz; if(N < 256){ sort(A, A+N); return; } bt = sizeof(unsigned) * 8; walloc1d(&arr, N, &mem); walloc1d(&sz, N, &mem); for(m=0;m>m)&255u) ]++; rep(i,1,257) sz[i] += sz[i-1]; rep(i,N){ c = ((A[i]>>m)&255u); arr[sz[c]++] = A[i]; } swap(A, arr); } } ------------------------------- sortF_int ------ void sortF_L(int N, int A[], void *mem = wmem){ int i, x, y, z; int *arr; unsigned *send; if(N < 256){ sort(A, A+N); return; } send = (unsigned*)A; sortF_L(N, send, mem); if(A[0] < 0 || A[N-1] >= 0) return; x = 0; y = N; while(x < y){ z = (x+y) / 2; if(A[z] < 0) y = z; else x = z+1; } walloc1d(&arr, N, &mem); z = 0; rep(i,x,N) arr[z++] = A[i]; rep(i,x) arr[z++] = A[i]; rep(i,N) A[i] = arr[i]; } ------------------------------- sortF_ull ------ void sortF_L(int N, ull A[], void *mem = wmem){ int i, m, bt; ull *arr; unsigned c; int *sz; if(N < 512){ sort(A, A+N); return; } bt = sizeof(ull) * 8; walloc1d(&arr, N, &mem); walloc1d(&sz, N, &mem); for(m=0;m>m)&255u) ]++; rep(i,1,257) sz[i] += sz[i-1]; rep(i,N){ c = ((A[i]>>m)&255u); arr[sz[c]++] = A[i]; } swap(A, arr); } } ------------------------------- sortF_ll ------ void sortF_L(int N, ll A[], void *mem = wmem){ int i, x, y, z; ll *arr; ull *send; if(N < 512){ sort(A, A+N); return; } send = (ull*)A; sortF_L(N, send, mem); if(A[0] < 0 || A[N-1] >= 0) return; x = 0; y = N; while(x < y){ z = (x+y) / 2; if(A[z] < 0) y = z; else x = z+1; } walloc1d(&arr, N, &mem); z = 0; rep(i,x,N) arr[z++] = A[i]; rep(i,x) arr[z++] = A[i]; rep(i,N) A[i] = arr[i]; } ------------------------------- Kth0_size2 ------ template inline T1 Kth0_L(const T1 a, const T2 b){ if(a <= b) return a; return b; } ------------------------------- Kth1_size2 ------ template inline T1 Kth1_L(const T1 a, const T2 b){ if(a >= b) return a; return b; } ------------------------------- Kth0_size3 ------ template inline T1 Kth0_L(const T1 a, const T2 b, const T3 c){ if(a <= b){ if(a <= c) return a; return c; } if(b <= c) return b; return c; } ------------------------------- Kth1_size3 ------ template inline T1 Kth1_L(const T1 a, const T2 b, const T3 c){ if(a <= b){ if(b <= c) return b; if(c <= a) return a; return c; } if(a <= c) return a; if(c <= b) return b; return c; } ------------------------------- Kth2_size3 ------ template inline T1 Kth2_L(const T1 a, const T2 b, const T3 c){ if(a <= b){ if(b <= c) return c; return b; } if(a <= c) return c; return a; } ------------------------------- Kth0_size4 ------ template inline T1 Kth0_L(const T1 a, const T2 b, const T3 c, const T4 d){ if(a <= b){ if(a <= c){ if(a <= d) return a; return d; } if(c <= d) return c; return d; } if(b <= c){ if(b <= d) return b; return d; } if(c <= d) return c; return d; } ------------------------------- Kth1_size4 ------ template inline T1 Kth1_L(const T1 a, const T2 b, const T3 c, const T4 d){ if(a <= b){ if(c <= d){ if(a <= c){ if(b <= c) return b; return c; } if(a <= d) return a; return d; } if(a <= d){ if(b <= d) return b; return d; } if(a <= c) return a; return c; } if(c <= d){ if(b <= c){ if(a <= c) return a; return c; } if(b <= d) return b; return d; } if(b <= d){ if(a <= d) return a; return d; } if(b <= c) return b; return c; } ------------------------------- Kth2_size4 ------ template inline T1 Kth2_L(const T1 a, const T2 b, const T3 c, const T4 d){ if(a >= b){ if(c >= d){ if(a >= c){ if(b >= c) return b; return c; } if(a >= d) return a; return d; } if(a >= d){ if(b >= d) return b; return d; } if(a >= c) return a; return c; } if(c >= d){ if(b >= c){ if(a >= c) return a; return c; } if(b >= d) return b; return d; } if(b >= d){ if(a >= d) return a; return d; } if(b >= c) return b; return c; } ------------------------------- Kth3_size4 ------ template inline T1 Kth3_L(const T1 a, const T2 b, const T3 c, const T4 d){ if(a >= b){ if(a >= c){ if(a >= d) return a; return d; } if(c >= d) return c; return d; } if(b >= c){ if(b >= d) return b; return d; } if(c >= d) return c; return d; } ------------------------------- KthA ------ template T KthA_L(const int K, const int N, const T A[], void *mem = wmem){ int i; T *a; walloc1d(&a, N, &mem); rep(i,N) a[i] = A[i]; nth_element(a, a+K, a+N); return a[K]; } ------------------------------- next_mcomb ------ int next_mcomb(int len, int arr[], int lim){ int i; rrep(i,len){ if(arr[i]+1 < lim){ arr[i]++; i++; while(i < len){ arr[i] = arr[i-1]; i++; } return 1; } arr[i] = 0; } rep(i,len) arr[i] = 0; return 0; } ------------------------------- next_scomb ------ int next_scomb(int len, int arr[], int lim){ int i; rrep(i,len){ if(arr[i] < lim+i-len){ arr[i]++; i++; while(i < len){ arr[i] = arr[i-1] + 1; i++; } return 1; } arr[i] = 0; } rep(i,len) arr[i] = i; return 0; } ------------------------------- next_marr ------ int next_marr(int len, int arr[], int lim){ int i; rrep(i,len){ if(arr[i]+1 < lim) arr[i]++, return 1; arr[i] = 0; } return 0; } ------------------------------- next_sarr ------ int next_sarr(int len, int arr[], int lim, void *mem = wmem){ int i, j; char *use; walloc1d(&use, lim, &mem); rep(i,lim) use[i] = 0; rep(i,len) use[arr[i]]++; rrep(i,len){ use[arr[i]++] = 0; while(arr[i] < lim && use[arr[i]]) arr[i]++; if(arr[i] == lim) continue; use[arr[i++]] = 1; j = 0; while(i < len){ while(use[j]) j++; arr[i++] = j; use[j] = 1; } return 1; } rep(i,len){ arr[i] = i; use[i] = 1; } return 0; } ------------------------------- next_sarr_s ------ template int next_sarr_s(int len, int arr[], int lim, T use[]){ int i, j; rrep(i,len){ use[arr[i]++] = 0; while(arr[i] < lim && use[arr[i]]) arr[i]++; if(arr[i] == lim) continue; use[arr[i++]] = 1; j = 0; while(i < len){ while(use[j]) j++; arr[i++] = j; use[j] = 1; } return 1; } rep(i,len){ arr[i] = i; use[i] = 1; } return 0; } ------------------------------- Timer ------ struct Timer{ double x; double gettimeofday_sec(void){ timeval t; gettimeofday(&t, 0); return t.tv_sec + t.tv_usec * 1e-6; } void set(void){ x = gettimeofday_sec(); } double get(void){ return gettimeofday_sec() - x; } }; ------------------------------- Rand ------ struct Rand{ unsigned x,y,z,w; Rand(void){ x=123456789, y=362436069, z=521288629, w=(unsigned)time(NULL); } Rand(unsigned seed){ x=123456789, y=362436069, z=521288629, w=seed; } inline unsigned get(void){ unsigned t; t = (x^(x<<11)); x=y; y=z; z=w; w = (w^(w>>19))^(t^(t>>8)); return w; } inline double getUni(void){ return get()/4294967296.0; } inline int get(int a){ return (int)(a*getUni()); } inline int get(int a, int b){ return a+(int)((b-a+1)*getUni()); } inline ll get(ll a){ return(ll)(a*getUni()); } inline ll get(ll a, ll b){ return a+(ll)((b-a+1)*getUni()); } inline double get(double a, double b){ return a+(b-a)*getUni(); } inline int getExp(int a){ return(int)(exp(getUni()*log(a+1.0))-1.0); } inline int getExp(int a, int b){ return a+(int)(exp(getUni()*log((b-a+1)+1.0))-1.0); } }; ------------------------------- Modint ------ struct Modint{ unsigned val; Modint(){val=0;} Modint(int a){val = ord(a);} Modint(unsigned a){val = ord(a);} Modint(ll a){val = ord(a);} Modint(ull a){val = ord(a);} inline unsigned ord(unsigned a){ return a%MD; } inline unsigned ord(int a){ a %= (int)MD; if(a < 0) a += MD; return a; } inline unsigned ord(ull a){ return a%MD; } inline unsigned ord(ll a){ a %= (int)MD; if(a < 0) a += MD; return a; } inline unsigned get(){ return val; } inline Modint &operator++(){ val++; if(val >= MD) val -= MD; return *this; } inline Modint &operator--(){ if(val == 0) val = MD - 1; else --val; return *this; } inline Modint operator++(int a){ Modint res(*this); val++; if(val >= MD) val -= MD; return res; } inline Modint operator--(int a){ Modint res(*this); if(val == 0) val = MD - 1; else --val; return res; } inline Modint &operator+=(Modint a){ val += a.val; if(val >= MD) val -= MD; return *this; } inline Modint &operator-=(Modint a){ if(val < a.val) val = val + MD - a.val; else val -= a.val; return *this; } inline Modint &operator*=(Modint a){ val = ((ull)val*a.val)%MD; return *this; } inline Modint &operator/=(Modint a){ return *this *= a.inverse(); } inline Modint operator+(Modint a){ return Modint(*this)+=a; } inline Modint operator-(Modint a){ return Modint(*this)-=a; } inline Modint operator*(Modint a){ return Modint(*this)*=a; } inline Modint operator/(Modint a){ return Modint(*this)/=a; } inline Modint operator+(int a){ return Modint(*this)+=Modint(a); } inline Modint operator-(int a){ return Modint(*this)-=Modint(a); } inline Modint operator*(int a){ return Modint(*this)*=Modint(a); } inline Modint operator/(int a){ return Modint(*this)/=Modint(a); } inline Modint operator+(ll a){ return Modint(*this)+=Modint(a); } inline Modint operator-(ll a){ return Modint(*this)-=Modint(a); } inline Modint operator*(ll a){ return Modint(*this)*=Modint(a); } inline Modint operator/(ll a){ return Modint(*this)/=Modint(a); } inline Modint operator-(void){ Modint res; if(val) res.val=MD-val; else res.val=0; return res; } inline operator bool(void){ return val!=0; } inline operator int(void){ return get(); } inline operator ll(void){ return get(); } inline Modint inverse(){ int a = val, b = MD, u = 1, v = 0, t; Modint res; while(b){ t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } if(u < 0) u += MD; res.val = u; return res; } inline Modint pw(ull b){ Modint a(*this), res; res.val = 1; while(b){ if(b&1) res *= a; b >>= 1; a *= a; } return res; } inline bool operator==(int a){return ord(a)==val;} inline bool operator!=(int a){return ord(a)!=val;} }; inline Modint operator+(int a, Modint b){return Modint(a)+=b;} inline Modint operator-(int a, Modint b){return Modint(a)-=b;} inline Modint operator*(int a, Modint b){return Modint(a)*=b;} inline Modint operator/(int a, Modint b){return Modint(a)/=b;} inline Modint operator+(ll a, Modint b){return Modint(a)+=b;} inline Modint operator-(ll a, Modint b){return Modint(a)-=b;} inline Modint operator*(ll a, Modint b){return Modint(a)*=b;} inline Modint operator/(ll a, Modint b){return Modint(a)/=b;} ------------------------------- modint ------ struct modint{ static unsigned md; unsigned val; modint(){val=0;} modint(int a){val = ord(a);} modint(unsigned a){val = ord(a);} modint(ll a){val = ord(a);} modint(ull a){val = ord(a);} void setmod(unsigned m){ md = m; } unsigned ord(unsigned a){ return a%md; } unsigned ord(int a){ a %= (int)md; if(a < 0) a += md; return a; } unsigned ord(ull a){ return a%md; } unsigned ord(ll a){ a %= (int)md; if(a < 0) a += md; return a; } unsigned get(){ return val; } inline modint &operator++(){ val++; if(val >= md) val -= md; return *this; } inline modint &operator--(){ if(val == 0) val = md - 1; else --val; return *this; } inline modint operator++(int a){ modint res(*this); val++; if(val >= md) val -= md; return res; } inline modint operator--(int a){ modint res(*this); if(val == 0) val = md - 1; else --val; return res; } modint &operator+=(modint a){ val += a.val; if(val >= md) val -= md; return *this; } modint &operator-=(modint a){ if(val < a.val) val = val + md - a.val; else val -= a.val; return *this; } modint &operator*=(modint a){ val = ((ull)val*a.val)%md; return *this; } modint &operator/=(modint a){ return *this *= a.inverse(); } modint operator+(modint a){ return modint(*this)+=a; } modint operator-(modint a){ return modint(*this)-=a; } modint operator*(modint a){ return modint(*this)*=a; } modint operator/(modint a){ return modint(*this)/=a; } modint operator+(int a){ return modint(*this)+=modint(a); } modint operator-(int a){ return modint(*this)-=modint(a); } modint operator*(int a){ return modint(*this)*=modint(a); } modint operator/(int a){ return modint(*this)/=modint(a); } modint operator+(ll a){ return modint(*this)+=modint(a); } modint operator-(ll a){ return modint(*this)-=modint(a); } modint operator*(ll a){ return modint(*this)*=modint(a); } modint operator/(ll a){ return modint(*this)/=modint(a); } modint operator-(void){ modint res; if(val) res.val=md-val; else res.val=0; return res; } operator bool(void){ return val!=0; } operator int(void){ return get(); } operator ll(void){ return get(); } modint inverse(){ int a = val, b = md, u = 1, v = 0, t; modint res; while(b){ t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } if(u < 0) u += md; res.val = u; return res; } modint pw(ull b){ modint a(*this), res; res.val = 1; while(b){ if(b&1) res *= a; b >>= 1; a *= a; } return res; } bool operator==(int a){return ord(a)==val;} bool operator!=(int a){return ord(a)!=val;} }; unsigned modint::md; modint operator+(int a, modint b){return modint(a)+=b;} modint operator-(int a, modint b){return modint(a)-=b;} modint operator*(int a, modint b){return modint(a)*=b;} modint operator/(int a, modint b){return modint(a)/=b;} modint operator+(ll a, modint b){return modint(a)+=b;} modint operator-(ll a, modint b){return modint(a)-=b;} modint operator*(ll a, modint b){return modint(a)*=b;} modint operator/(ll a, modint b){return modint(a)/=b;} ------------------------------- modint_init ------ {modint x; x.setmod(MD);} ------------------------------- Mint ------ struct Mint{ unsigned val; Mint(){val=0;} Mint(int a){val = mulR(a);} Mint(unsigned a){val = mulR(a);} Mint(ll a){val = mulR(a);} Mint(ull a){val = mulR(a);} inline unsigned mulR(unsigned a){ return (ull)a*MINT_R%MD; } inline unsigned mulR(int a){ if(a < 0) a = a%((int)MD)+(int)MD; return mulR((unsigned)a); } inline unsigned mulR(ull a){ return mulR((unsigned)(a%MD)); } inline unsigned mulR(ll a){ a %= (int)MD; if(a < 0) a += MD; return mulR((unsigned)a); } inline unsigned reduce(unsigned T){ unsigned m = T * MINT_MDNINV; unsigned t = (unsigned)((T + (ull)m*MD) >> MINT_W); if(t >= MD) t -= MD; return t; } inline unsigned reduce(ull T){ unsigned m = (unsigned)T * MINT_MDNINV; unsigned t = (unsigned)((T + (ull)m*MD) >> MINT_W); if(t >= MD) t -= MD; return t; } inline unsigned get(){ return reduce(val); } inline Mint &operator++(){ (*this) += 1; return *this; } inline Mint &operator--(){ (*this) -= 1; return *this; } inline Mint operator++(int a){ Mint res(*this); (*this) += 1; return res; } inline Mint operator--(int a){ Mint res(*this); (*this) -= 1; return res; } inline Mint &operator+=(Mint a){ val += a.val; if(val >= MD) val -= MD; return *this; } inline Mint &operator-=(Mint a){ if(val < a.val) val = val + MD - a.val; else val -= a.val; return *this; } inline Mint &operator*=(Mint a){ val = reduce((ull)val*a.val); return *this; } inline Mint &operator/=(Mint a){ return *this *= a.inverse(); } inline Mint operator+(Mint a){ return Mint(*this)+=a; } inline Mint operator-(Mint a){ return Mint(*this)-=a; } inline Mint operator*(Mint a){ return Mint(*this)*=a; } inline Mint operator/(Mint a){ return Mint(*this)/=a; } inline Mint operator+(int a){ return Mint(*this)+=Mint(a); } inline Mint operator-(int a){ return Mint(*this)-=Mint(a); } inline Mint operator*(int a){ return Mint(*this)*=Mint(a); } inline Mint operator/(int a){ return Mint(*this)/=Mint(a); } inline Mint operator+(ll a){ return Mint(*this)+=Mint(a); } inline Mint operator-(ll a){ return Mint(*this)-=Mint(a); } inline Mint operator*(ll a){ return Mint(*this)*=Mint(a); } inline Mint operator/(ll a){ return Mint(*this)/=Mint(a); } inline Mint operator-(void){ Mint res; if(val) res.val=MD-val; else res.val=0; return res; } inline operator bool(void){ return val!=0; } inline operator int(void){ return get(); } inline operator ll(void){ return get(); } inline Mint inverse(){ int a = val, b = MD, u = 1, v = 0, t; Mint res; while(b){ t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } if(u < 0) u += MD; res.val = (ull)u*MINT_RR % MD; return res; } inline Mint pw(ull b){ Mint a(*this), res; res.val = MINT_R; while(b){ if(b&1) res *= a; b >>= 1; a *= a; } return res; } inline bool operator==(int a){return mulR(a)==val;} inline bool operator!=(int a){return mulR(a)!=val;} }; inline Mint operator+(int a, Mint b){return Mint(a)+=b;} inline Mint operator-(int a, Mint b){return Mint(a)-=b;} inline Mint operator*(int a, Mint b){return Mint(a)*=b;} inline Mint operator/(int a, Mint b){return Mint(a)/=b;} inline Mint operator+(ll a, Mint b){return Mint(a)+=b;} inline Mint operator-(ll a, Mint b){return Mint(a)-=b;} inline Mint operator*(ll a, Mint b){return Mint(a)*=b;} inline Mint operator/(ll a, Mint b){return Mint(a)/=b;} ------------------------------- mint ------ struct mint{ static unsigned md, W, R, Rinv, mdninv, RR; unsigned val; mint(){val=0;} mint(int a){val = mulR(a);} mint(unsigned a){val = mulR(a);} mint(ll a){val = mulR(a);} mint(ull a){val = mulR(a);} int get_inv(ll a, int md){ll t=a,s=md,u=1,v=0,e;while(s){e=t/s;t-=e*s;u-=e*v;swap(t,s);swap(u,v);}if(u<0)u+=md;return u;} void setmod(unsigned m){ int i; unsigned t; W = 32; md = m; R = (1ULL << W) % md; RR = (ull)R*R % md; switch(m){ case 104857601: Rinv = 2560000; mdninv = 104857599; break; case 998244353: Rinv = 232013824; mdninv = 998244351; break; case 1000000007: Rinv = 518424770; mdninv = 2226617417U; break; case 1000000009: Rinv = 171601999; mdninv = 737024967; break; case 1004535809: Rinv = 234947584; mdninv = 1004535807; break; case 1007681537: Rinv = 236421376; mdninv = 1007681535; break; case 1012924417: Rinv = 238887936; mdninv = 1012924415; break; case 1045430273: Rinv = 254466304; mdninv = 1045430271; break; case 1051721729: Rinv = 257538304; mdninv = 1051721727; break; default: Rinv = get_inv(R, md); mdninv = 0; t = 0; rep(i,(int)W){ if(t%2==0) t+=md, mdninv |= (1U<> W); if(t >= md) t -= md; return t; } unsigned reduce(ull T){ unsigned m = (unsigned)T * mdninv; unsigned t = (unsigned)((T + (ull)m*md) >> W); if(t >= md) t -= md; return t; } unsigned get(){ return reduce(val); } inline mint &operator++(){ (*this) += 1; return *this; } inline mint &operator--(){ (*this) -= 1; return *this; } inline mint operator++(int a){ mint res(*this); (*this) += 1; return res; } inline mint operator--(int a){ mint res(*this); (*this) -= 1; return res; } mint &operator+=(mint a){ val += a.val; if(val >= md) val -= md; return *this; } mint &operator-=(mint a){ if(val < a.val) val = val + md - a.val; else val -= a.val; return *this; } mint &operator*=(mint a){ val = reduce((ull)val*a.val); return *this; } mint &operator/=(mint a){ return *this *= a.inverse(); } mint operator+(mint a){ return mint(*this)+=a; } mint operator-(mint a){ return mint(*this)-=a; } mint operator*(mint a){ return mint(*this)*=a; } mint operator/(mint a){ return mint(*this)/=a; } mint operator+(int a){ return mint(*this)+=mint(a); } mint operator-(int a){ return mint(*this)-=mint(a); } mint operator*(int a){ return mint(*this)*=mint(a); } mint operator/(int a){ return mint(*this)/=mint(a); } mint operator+(ll a){ return mint(*this)+=mint(a); } mint operator-(ll a){ return mint(*this)-=mint(a); } mint operator*(ll a){ return mint(*this)*=mint(a); } mint operator/(ll a){ return mint(*this)/=mint(a); } mint operator-(void){ mint res; if(val) res.val=md-val; else res.val=0; return res; } operator bool(void){ return val!=0; } operator int(void){ return get(); } operator ll(void){ return get(); } mint inverse(){ int a = val, b = md, u = 1, v = 0, t; mint res; while(b){ t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } if(u < 0) u += md; res.val = (ull)u*RR % md; return res; } mint pw(ull b){ mint a(*this), res; res.val = R; while(b){ if(b&1) res *= a; b >>= 1; a *= a; } return res; } bool operator==(int a){return mulR(a)==val;} bool operator!=(int a){return mulR(a)!=val;} }; unsigned mint::md, mint::W, mint::R, mint::Rinv, mint::mdninv, mint::RR; mint operator+(int a, mint b){return mint(a)+=b;} mint operator-(int a, mint b){return mint(a)-=b;} mint operator*(int a, mint b){return mint(a)*=b;} mint operator/(int a, mint b){return mint(a)/=b;} mint operator+(ll a, mint b){return mint(a)+=b;} mint operator-(ll a, mint b){return mint(a)-=b;} mint operator*(ll a, mint b){return mint(a)*=b;} mint operator/(ll a, mint b){return mint(a)/=b;} ------------------------------- mint_init ------ {mint x; x.setmod(MD);} ------------------------------- readerFile ------ inplace_L FILE *readerfp = stdin; inplace_L int readermode = 0; void readerFile(){ if(readermode) fclose(readerfp); readerfp = stdin; readermode = 0; } void readerFile(string filename, string mode = "r"){ if(readermode) fclose(readerfp); readerfp = fopen(filename.c_str(), mode.c_str()); readermode = 1; } void readerFile(FILE *fp){ if(readermode) fclose(readerfp); readerfp = fp; readermode = 0; } ------------------------------- my_getchar_unlocked ------ inline int my_getchar_unlocked(){ static char buf[1048576]; static int s = 1048576, e = 1048576; if(s == e && e == 1048576){ e = fread_unlocked(buf, 1, 1048576, stdin); s = 0; } if(s == e) return EOF; return buf[s++]; } ------------------------------- reader_all ------ ------------------------------- reader_int ------ inline void rd(int &x){ int k, m=0; x=0; for(;;){ k = my_getchar_unlocked(); if(k=='-'){ m=1; break; } if('0'<=k&&k<='9'){ x=k-'0'; break; } } for(;;){ k = my_getchar_unlocked(); if(k<'0'||k>'9'){ break; } x=x*10+k-'0'; } if(m){ x=-x; } } ------------------------------- reader_unsigned ------ inline void rd(unsigned &x){ int k; x=0; for(;;){ k = my_getchar_unlocked(); if('0'<=k&&k<='9'){ x=k-'0'; break; } } for(;;){ k = my_getchar_unlocked(); if(k<'0'||k>'9'){ break; } x=x*10+k-'0'; } } ------------------------------- reader_ll ------ inline void rd(ll &x){ int k, m=0; x=0; for(;;){ k = my_getchar_unlocked(); if(k=='-'){ m=1; break; } if('0'<=k&&k<='9'){ x=k-'0'; break; } } for(;;){ k = my_getchar_unlocked(); if(k<'0'||k>'9'){ break; } x=x*10+k-'0'; } if(m){ x=-x; } } ------------------------------- reader_ull ------ inline void rd(ull &x){ int k; x=0; for(;;){ k = my_getchar_unlocked(); if('0'<=k&&k<='9'){ x=k-'0'; break; } } for(;;){ k = my_getchar_unlocked(); if(k<'0'||k>'9'){ break; } x=x*10+k-'0'; } } ------------------------------- reader_int128 ------ inline void rd(__int128_t &x){ int k, m=0; x=0; for(;;){ k = my_getchar_unlocked(); if(k=='-'){ m=1; break; } if('0'<=k&&k<='9'){ x=k-'0'; break; } } for(;;){ k = my_getchar_unlocked(); if(k<'0'||k>'9'){ break; } x=x*10+k-'0'; } if(m){ x=-x; } } ------------------------------- reader_uint128 ------ inline void rd(__uint128_t &x){ int k; x=0; for(;;){ k = my_getchar_unlocked(); if('0'<=k&&k<='9'){ x=k-'0'; break; } } for(;;){ k = my_getchar_unlocked(); if(k<'0'||k>'9'){ break; } x=x*10+k-'0'; } } ------------------------------- reader_Modint ------ inline void rd(Modint &x){int i; rd(i); x=i;} ------------------------------- reader_modint ------ inline void rd(modint &x){int i; rd(i); x=i;} ------------------------------- reader_Mint ------ inline void rd(Mint &x){int i; rd(i); x=i;} ------------------------------- reader_mint ------ inline void rd(mint &x){int i; rd(i); x=i;} ------------------------------- reader_double ------ inline void rd(double &x){ int k, m=0, p=0; double r = 1; x = 0; for(;;){ k = my_getchar_unlocked(); if(k=='-') m = 1, break; if(k=='.') p = 1, break; if('0'<=k&&k<='9') x = k - '0', break; } for(;;){ k = my_getchar_unlocked(); if(k=='.') p = 1, continue; if(k<'0'||k>'9') break; if(p){ r *= 0.1; x += r * (k - '0'); } else { x = x * 10 + k - '0'; } } if(m) x = -x; } ------------------------------- reader_char ------ inline void rd(char &c){ int i; for(;;){ i = my_getchar_unlocked(); if(i!=' '&&i!='\n'&&i!='\r'&&i!='\t'&&i!=EOF) break; } c = i; } ------------------------------- reader_char_array ------ inline int rd(char c[]){ int i, sz = 0; for(;;){ i = my_getchar_unlocked(); if(i!=' '&&i!='\n'&&i!='\r'&&i!='\t'&&i!=EOF) break; } c[sz++] = i; for(;;){ i = my_getchar_unlocked(); if(i==' '||i=='\n'||i=='\r'||i=='\t'||i==EOF) break; c[sz++] = i; } c[sz]='\0'; return sz; } ------------------------------- reader_string ------ inline void rd(string &x){ char *buf = (char *)wmem; rd(buf); x = buf; } ------------------------------- rdLine ------ inline int rdLine_L(char c[]){ int i, sz = 0; for(;;){ i = my_getchar_unlocked(); if(i=='\r') continue; if(i=='\n') break; if(i==EOF){ if(sz==0){ c[sz] = '\0'; return -1; } break; } c[sz++] = i; } c[sz]='\0'; return sz; } ------------------------------- rd_int ------ inline int rd_int(void){int x; rd(x); return x;} ------------------------------- rd_ll ------ inline ll rd_ll(void){ll x; rd(x); return x;} ------------------------------- rd_string ------ inline string rd_string(void){string x; rd(x); return x;} ------------------------------- writerFile ------ inplace_L FILE *writerfp = stdout; inplace_L int writermode = 0; void writerFile(){ if(writermode) fclose(writerfp); writerfp = stdout; writermode = 0; } void writerFile(string filename, string mode = "w"){ if(writermode) fclose(writerfp); writerfp = fopen(filename.c_str(), mode.c_str()); writermode = 1; } void writerFile(FILE *fp){ if(writermode) fclose(writerfp); writerfp = fp; writermode = 0; } ------------------------------- my_putchar_unlocked ------ struct MY_WRITER { char buf[1048576]; int s, e; MY_WRITER(){ s = 0; e = 1048576; } ~MY_WRITER(){ if(s) fwrite_unlocked(buf, 1, s, stdout); } }; inplace_L MY_WRITER MY_WRITER_VAR; void my_putchar_unlocked(int a){ if(MY_WRITER_VAR.s == MY_WRITER_VAR.e){ fwrite_unlocked(MY_WRITER_VAR.buf, 1, MY_WRITER_VAR.s, stdout); MY_WRITER_VAR.s = 0; } MY_WRITER_VAR.buf[MY_WRITER_VAR.s++] = a; } ------------------------------- writer_vector_head ------ template inline void wt_L(const vector &x); ------------------------------- writer_vector ------ template inline void wt_L(const vector &x){ int fg = 0; for(auto a : x){ if(fg) my_putchar_unlocked(' '); fg = 1; wt_L(a); } } ------------------------------- writer_set_head ------ template inline void wt_L(const set &x); ------------------------------- writer_set ------ template inline void wt_L(const set &x){ int fg = 0; for(auto a : x){ if(fg) my_putchar_unlocked(' '); fg = 1; wt_L(a); } } ------------------------------- writer_multiset_head ------ template inline void wt_L(const multiset &x); ------------------------------- writer_multiset ------ template inline void wt_L(const multiset &x){ int fg = 0; for(auto a : x){ if(fg) my_putchar_unlocked(' '); fg = 1; wt_L(a); } } ------------------------------- writer_pair_head ------ template inline void wt_L(const pair x); ------------------------------- writer_pair ------ template inline void wt_L(const pair x){ wt_L(x.first); my_putchar_unlocked(' '); wt_L(x.second); } ------------------------------- writer_all ------ ------------------------------- writer_char ------ inline void wt_L(const char a){ my_putchar_unlocked(a); } ------------------------------- writer_int ------ inline void wt_L(int x){ int s=0, m=0; char f[10]; if(x<0) m=1, x=-x; while(x) f[s++]=x%10, x/=10; if(!s) f[s++]=0; if(m) my_putchar_unlocked('-'); while(s--) my_putchar_unlocked(f[s]+'0'); } ------------------------------- writer_int_withBase ------ inline void wt_L(int x, int b){ int s=0, m=0; char f[35]; if(x<0) m=1, x=-x; while(x) f[s++]=x%b, x/=b; if(!s) f[s++]=0; if(m) my_putchar_unlocked('-'); while(s--) my_putchar_unlocked("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[f[s]]); } ------------------------------- writer_unsigned ------ inline void wt_L(unsigned x){ int s=0; char f[10]; while(x) f[s++]=x%10, x/=10; if(!s) f[s++]=0; while(s--) my_putchar_unlocked(f[s]+'0'); } ------------------------------- writer_ll ------ inline void wt_L(ll x){ int s=0, m=0; char f[20]; if(x<0) m=1, x=-x; while(x) f[s++]=x%10, x/=10; if(!s) f[s++]=0; if(m) my_putchar_unlocked('-'); while(s--) my_putchar_unlocked(f[s]+'0'); } ------------------------------- writer_ll_withBase ------ inline void wt_L(ll x, int b){ int s=0, m=0; char f[70]; if(x<0) m=1, x=-x; while(x) f[s++]=x%b, x/=b; if(!s) f[s++]=0; if(m) my_putchar_unlocked('-'); while(s--) my_putchar_unlocked("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[f[s]]); } ------------------------------- writer_ull ------ inline void wt_L(ull x){ int s=0; char f[21]; while(x) f[s++]=x%10, x/=10; if(!s) f[s++]=0; while(s--) my_putchar_unlocked(f[s]+'0'); } ------------------------------- writer_int128 ------ inline void wt_L(__int128_t x){ int s=0, m=0; char f[40]; if(x<0) m=1, x=-x; while(x) f[s++]=x%10, x/=10; if(!s) f[s++]=0; if(m) my_putchar_unlocked('-'); while(s--) my_putchar_unlocked(f[s]+'0'); } ------------------------------- writer_uint128 ------ inline void wt_L(__uint128_t x){ int s=0; char f[40]; while(x) f[s++]=x%10, x/=10; if(!s) f[s++]=0; while(s--) my_putchar_unlocked(f[s]+'0'); } ------------------------------- writer_Modint ------ inline void wt_L(Modint x){int i; i = (int)x; wt_L(i);} ------------------------------- writer_modint ------ inline void wt_L(modint x){int i; i = (int)x; wt_L(i);} ------------------------------- writer_Mint ------ inline void wt_L(Mint x){int i; i = (int)x; wt_L(i);} ------------------------------- writer_mint ------ inline void wt_L(mint x){int i; i = (int)x; wt_L(i);} ------------------------------- writer_double ------ inplace_L int WRITER_DOUBLE_DIGIT = 15; inline int writerDigit_double(){ return WRITER_DOUBLE_DIGIT; } inline void writerDigit_double(int d){ WRITER_DOUBLE_DIGIT = d; } inline void wt_L(double x){ const int d = WRITER_DOUBLE_DIGIT; int k, r; double v; if(x!=x || (x==x+1 && x==2*x)){ my_putchar_unlocked('E'); my_putchar_unlocked('r'); my_putchar_unlocked('r'); return; } if(x < 0){ my_putchar_unlocked('-'); x = -x; } x += 0.5 * pow(0.1, d); r = 0; v = 1; while(x >= 10*v) v *= 10, r++; while(r >= 0){ r--; k = floor(x / v); if(k >= 10) k = 9; if(k <= -1) k = 0; x -= k * v; v *= 0.1; my_putchar_unlocked(k + '0'); } if(d > 0){ my_putchar_unlocked('.'); v = 1; rep(r,d){ v *= 0.1; k = floor(x / v); if(k >= 10) k = 9; if(k <= -1) k = 0; x -= k * v; my_putchar_unlocked(k + '0'); } } } ------------------------------- writer_char_array ------ inline void wt_L(const char c[]){ int i=0; for(i=0;c[i]!='\0';i++) my_putchar_unlocked(c[i]); } ------------------------------- writer_string ------ inline void wt_L(const string &x){ int i=0; for(i=0;x[i]!='\0';i++){ my_putchar_unlocked(x[i]); } } ------------------------------- Matrix ------ template struct Matrix { int r, c, mem; T *dat; Matrix(){r=c=mem = 0;} Matrix(const int rr, const int cc){ if(rr == 0 || cc == 0){ r = c = 0; } else { r = rr; c = cc; } mem = r * c; if(mem > 0) dat = new T[mem]; } Matrix(const Matrix &a){ int i; r = a.r; c = a.c; mem = r * c; dat = new T[mem]; rep(i,mem) dat[i] = a.dat[i]; } ~Matrix(){ if(mem) delete [] dat; } void changeSize(const int rr, const int cc){ if(rr==0 || cc==0){ r = c = 0; } else { r = rr; c = cc; } if(mem < r*c){ if(mem) delete [] dat; mem = r*c; dat = new T[mem]; } } Matrix& operator=(const Matrix &a){ int i, j; r = a.r; c = a.c; j = r * c; changeSize(r,c); rep(i,j) dat[i] = a.dat[i]; return *this; } Matrix& operator=(const int a){ int i, j; j = r * c; rep(i,j) dat[i] = 0; j = min(r,c); rep(i,j) dat[i*c+i] = a; return *this; } Matrix& operator+=(const Matrix &a){ int i, j; if(r==0 || r!=a.r || c!=a.c){ changeSize(0,0); return *this; } j = r*c; rep(i,j) dat[i] += a.dat[i]; return *this; } Matrix operator+(const Matrix &a){ return Matrix(*this) += a; } Matrix& operator-=(const Matrix &a){ int i, j; if(r==0 || r!=a.r || c!=a.c){ changeSize(0,0); return *this; } j = r*c; rep(i,j) dat[i] -= a.dat[i]; return *this; } Matrix operator-(const Matrix &a){ return Matrix(*this) -= a; } Matrix& operator*=(const Matrix &a){ int i, j, k, x; T *m; if(r==0 || c!=a.r){ changeSize(0,0); return *this; } m = (T*)wmem; x = r * a.c; rep(i,x) m[i] = 0; rep(i,r) rep(k,c) rep(j,a.c) m[i*a.c+j] += dat[i*c+k] * a.dat[k*a.c+j]; changeSize(r, a.c); rep(i,x) dat[i] = m[i]; return *this; } Matrix operator*(const Matrix &a){ return Matrix(*this) *= a; } Matrix& operator*=(const int a){ int i, j; j = r * c; rep(i,j) dat[i] *= a; return *this; } Matrix& operator*=(const ll a){ int i, j; j = r * c; rep(i,j) dat[i] *= a; return *this; } Matrix& operator*=(const double a){ int i, j; j = r * c; rep(i,j) dat[i] *= a; return *this; } inline T* operator[](const int a){ return dat+a*c; } }; template Matrix operator*(const int a, const Matrix &b){return Matrix(b)*=a;} template Matrix operator*(const Matrix &b, const int a){return Matrix(b)*=a;} template Matrix operator*(const ll a, const Matrix &b){return Matrix(b)*=a;} template Matrix operator*(const Matrix &b, const ll a){return Matrix(b)*=a;} template Matrix operator*(const double a, const Matrix &b){return Matrix(b)*=a;} template Matrix operator*(const Matrix &b, const double a){return Matrix(b)*=a;} template inline Matrix pow_L(Matrix a, S b){ int i, j; Matrix res; res.changeSize(a.r, a.c); res = 1; while(b){ if(b&1) res *= a; b >>= 1; a *= a; } return res; } ------------------------------- LIS_length ------ template int LIS_length(int n, T a[], void *mem = wmem){ int i, k, res; T *arr; if(n==0) return 0; walloc1d(&arr, n, &mem); arr[0] = a[0]; res = 1; REP(i,1,n){ k = lower_bound(arr, arr+res, a[i]) - arr; arr[k] = a[i]; if(res==k) res++; } return res; } ------------------------------- weaklyLIS_length ------ template int weaklyLIS_length(int n, T a[], void *mem = wmem){ int i, k, res; T *arr; if(n==0) return 0; walloc1d(&arr, n, &mem); arr[0] = a[0]; res = 1; REP(i,1,n){ k = upper_bound(arr, arr+res, a[i]) - arr; arr[k] = a[i]; if(res==k) res++; } return res; } ------------------------------- LIS_ends ------ template int LIS_ends(int n, T a[], S res[], void *mem = wmem){ int i, k, sz; T *arr; if(n==0) return 0; walloc1d(&arr, n, &mem); arr[0] = a[0]; res[0] = 1; sz = 1; REP(i,1,n){ k = lower_bound(arr, arr+sz, a[i]) - arr; arr[k] = a[i]; res[i] = k + 1; if(sz==k) sz++; } return sz; } ------------------------------- weaklyLIS_ends ------ template int weaklyLIS_ends(int n, T a[], S res[], void *mem = wmem){ int i, k, sz; T *arr; if(n==0) return 0; walloc1d(&arr, n, &mem); arr[0] = a[0]; res[0] = 1; sz = 1; REP(i,1,n){ k = upper_bound(arr, arr+sz, a[i]) - arr; arr[k] = a[i]; res[i] = k + 1; if(sz==k) sz++; } return sz; } ------------------------------- BIT_popcount ------ inline int BIT_popcount_L(const int x){ return __builtin_popcount(x); } inline int BIT_popcount_L(const ll x){ return __builtin_popcountll(x); } ------------------------------- BIT_ctz ------ inline int BIT_ctz_L(const int x){ return __builtin_ctz(x); } inline int BIT_ctz_L(const ll x){ return __builtin_ctzll(x); } ------------------------------- BIT_parity ------ inline int BIT_parity(const int x){ return __builtin_parity(x); } inline int BIT_parity(const ll x){ return __builtin_parityll(x); } ------------------------------- BIT_parity_pm ------ inline int BIT_parity_pm(const int x){ return 1 - 2 * __builtin_parity(x); } inline int BIT_parity_pm(const ll x){ return 1 - 2 * __builtin_parityll(x); } ------------------------------- Digit ------ template inline int Digit_L(T n){ int res = 0; while(n) res++, n /= 10; return res; } ------------------------------- Digit_base ------ template inline int Digit_L(T n, S b){ int res = 0; while(n) res++, n /= b; return res; } ------------------------------- Digit_all ------ template inline int Digit_L(T n, S res[]){ int sz = 0; while(n) res[sz++] = n % 10, n /= 10; return sz; } ------------------------------- Digit_all_base ------ template inline int Digit_L(T n, S res[], U b){ int sz = 0; while(n) res[sz++] = n % b, n /= b; return sz; } ------------------------------- DigitF_all ------ template inline void DigitF_L(T n, int sz, S res[]){ int i; rep(i,sz) res[i] = n % 10, n /= 10; } ------------------------------- DigitF_all_base ------ template inline void DigitF_L(T n, int sz, S res[], U b){ int i; rep(i,sz) res[i] = n % b, n /= b; } ------------------------------- invDigit ------ template inline T invDigit_L(int sz, T d[]){ T res = 0; int i; rrep(i,sz) res = 10 * res + d[i]; return res; } ------------------------------- invDigit_base ------ template inline T invDigit_L(int sz, T d[], S b){ T res = 0; int i; rrep(i,sz) res = b * res + d[i]; return res; } ------------------------------- sod ------ template inline int sod_L(T n){ int res = 0; while(n) res += n%10, n /= 10; return res; } ------------------------------- sod_base ------ template inline S sod_L(T n, S b){ S res = 0; while(n) res += n%b, n /= b; return res; } ------------------------------- prodDigits ------ template T prodDigits(T n){ T res = 1; if(n==0) return 0; while(n) res *= n % 10, n /= 10; return res; } ------------------------------- DigitHist ------ template inline int DigitHist(T n, S res[]){ int i, len = 0; rep(i,10) res[i] = 0; while(n){ len++; res[n%10]++; n /= 10; } return len; } ------------------------------- invDigit_r ------ template inline T invDigit_r(int sz, T d[]){ T res = 0; int i; rep(i,sz) res = 10 * res + d[i]; return res; } ------------------------------- STR2int ------ inline int STR2int(string s, const int b){ int i = 0, fg = 1; int res = 0; if(s[i] == '-') i++, fg = -fg; while(i < s.size()){ res = b * res; if('0' <= s[i] <= '9') res += s[i] - '0'; else if('A' <= s[i] <= 'Z') res += s[i] - 'A' + 10; else if('a' <= s[i] <= 'z') res += s[i] - 'a' + 36; i++; } return fg * res; } inline int STR2int(string s){ int i = 0, fg = 1; int res = 0; if(s[i] == '-') i++, fg = -fg; while(i < s.size()){ res = 10 * res + s[i] - '0'; i++; } return fg * res; } ------------------------------- STR2ll ------ inline ll STR2ll(string s, const int b){ int i = 0, fg = 1; ll res = 0; if(s[i] == '-') i++, fg = -fg; while(i < s.size()){ res = b * res; if('0' <= s[i] <= '9') res += s[i] - '0'; else if('A' <= s[i] <= 'Z') res += s[i] - 'A' + 10; else if('a' <= s[i] <= 'z') res += s[i] - 'a' + 36; i++; } return fg * res; } inline ll STR2ll(string s){ int i = 0, fg = 1; ll res = 0; if(s[i] == '-') i++, fg = -fg; while(i < s.size()){ res = 10 * res + s[i] - '0'; i++; } return fg * res; } ------------------------------- Prime ------ int Prime_L(int N, int res[], void *mem=wmem){ int i, a, b; int sz = 1; const int r = 23000; bool *isprime; int *sf, ss = 1; walloc1d(&isprime, r, &mem); walloc1d(&sf, r, &mem); N /= 2; res[0] = 2; b = min(r, N); rep(i,1,b) isprime[i] = 1; rep(i,1,b) if(isprime[i]){ res[sz++] = 2i+1; sf[ss] = 2i*(i+1); if(sf[ss] < N){ while(sf[ss] < r) isprime[sf[ss]] = 0, sf[ss] += res[ss]; ss++; } } for(a=r; a void intervalSieve(ll st, int len, T res[], int ps, int p[]){ int i; ll k = 2-st; rep(i,len) res[i] = 1; rep(i,k) res[i] = 0; rep(i,ps){ k = (ll)p[i]*p[i]; if(k >= st+len) break; if(k < st) k = (st+p[i]-1) / p[i] * p[i]; while(k < st+len){ res[k-st] = 0; k += p[i]; } } } ------------------------------- pow2 ------ template inline T pow2_L(T a){ return a*a; } ------------------------------- pow3 ------ template inline T pow3_L(T a){ return a*a*a; } ------------------------------- pow4 ------ template inline T pow4_L(T a){ return a*a*a*a; } ------------------------------- pow ------ template inline T pow_L(T a, S b){ T res = 1; res = 1; for(;;){ if(b&1) res *= a; b >>= 1; if(b==0) break; a *= a; } return res; } inline double pow_L(double a, double b){ return pow(a,b); } ------------------------------- powmod ------ ull powmod(ull a, ull b, ull m){ ull r = 1; while(b){ if(b&1) r = r * a % m; b>>=1; if(b) a = a * a % m; } return r; } ------------------------------- PowMod ------ template T PowMod(T a, P b, M m){ T r; r = 1; while(b > 0){ if(b % 2) r = r * a % m; b /= 2; if(b > 0) a = a * a % m; } return r; } ------------------------------- primitiveRoot ------ ll primitiveRoot(ll p, void *mem = wmem){ int ys; ll *y, r; if(!isPrime(p)) return -1; walloc1d(&y, 1d5, &mem); ys = Divisor(p-1, y, mem); rep(r,1,p){ rep(i,ys-1) if(powmod(r,y[i],p) == 1) break_continue; return r; } return -1; } ------------------------------- gcd ------ template inline T GCD_L(T a, U b){T r; while(b) r=a, a=b, b=r%a; return a;} ------------------------------- lcm ------ template inline T LCM_L(T a, U b){return a/GCD_L(a,b)*b;} ------------------------------- multiset_popFirst ------ template inline T popFirst(multiset &a){ T res = *(a.begin()); a.erase(a.begin()); return res; } ------------------------------- multiset_getFirst ------ template inline T getFirst(multiset &a){ return *(a.begin()); } ------------------------------- multiset_popLast ------ template inline T popLast(multiset &a){ T res; typename multiset::iterator it; it = a.end(); it--; res = *it; a.erase(it); return res; } ------------------------------- multiset_getLast ------ template inline T getLast(multiset &a){ typename multiset::iterator it; it = a.end(); it--; return *it; } ------------------------------- set_popFirst ------ template inline T popFirst(set &a){ T res = *(a.begin()); a.erase(a.begin()); return res; } ------------------------------- set_getFirst ------ template inline T getFirst(set &a){ return *(a.begin()); } ------------------------------- set_popLast ------ template inline T popLast(set &a){ T res; typename set::iterator it; it = a.end(); it--; res = *it; a.erase(it); return res; } ------------------------------- set_getLast ------ template inline T getLast(set &a){ typename set::iterator it; it = a.end(); it--; return *it; } ------------------------------- multiset_getClosest ------ template T getClosest(multiset &s, S v){ typename multiset::iterator it, jt; it = s.lower_bound(v); if(it==s.begin()) return *it; if(it==s.end()) return *(--it); jt = it; it--; if(v - (*it) <= (*jt) - v) return *it; return *jt; } ------------------------------- multiset_getClosestL ------ template T getClosestL(multiset &s, S v){ typename multiset::iterator it, jt; it = s.lower_bound(v); if(it==s.begin()) return *it; if(it==s.end()) return *(--it); jt = it; it--; if(v - (*it) < (*jt) - v) return *it; return *jt; } ------------------------------- set_getClosest ------ template T getClosest(set &s, S v){ typename set::iterator it, jt; it = s.lower_bound(v); if(it==s.begin()) return *it; if(it==s.end()) return *(--it); jt = it; it--; if(v - (*it) <= (*jt) - v) return *it; return *jt; } ------------------------------- set_getClosestL ------ template T getClosestL(set &s, S v){ typename set::iterator it, jt; it = s.lower_bound(v); if(it==s.begin()) return *it; if(it==s.end()) return *(--it); jt = it; it--; if(v - (*it) < (*jt) - v) return *it; return *jt; } ------------------------------- arr_getClosest ------ template T getClosest(int N, T A[], S val){ int i; i = lower_bound(A, A+N, val) - A; if(i==0) return A[0]; if(i==N) return A[N-1]; if(val - A[i-1] <= A[i] - val) return A[i-1]; return A[i]; } ------------------------------- arr_getClosestL ------ template T getClosestL(int N, T A[], S val){ int i; i = lower_bound(A, A+N, val) - A; if(i==0) return A[0]; if(i==N) return A[N-1]; if(val - A[i-1] < A[i] - val) return A[i-1]; return A[i]; } ------------------------------- combination_mint ------ struct combination_mint{ mint *fac, *ifac; void init(int n, void **mem = &wmem){ int i; walloc1d(&fac, n, mem); walloc1d(&ifac, n, mem); fac[0] = 1; rep(i,1,n) fac[i] = fac[i-1] * i; ifac[n-1] = 1 / fac[n-1]; for(i=n-2;i>=0;i--) ifac[i] = ifac[i+1] * (i+1); } mint C(int a, int b){ if(b < 0 || b > a) return 0; return fac[a]*ifac[b]*ifac[a-b]; } mint P(int a, int b){ if(b < 0 || b > a) return 0; return fac[a]*ifac[a-b]; } mint H(int a, int b){ if(a==0 && b==0) return 1; if(a<=0 || b<0) return 0; return C(a+b-1, b); } }; ------------------------------- reduceFraction ------ template void reduceFraction(T&a, U&b){T g=GCD_L(a,b);a/=g;b/=g;} ------------------------------- runLength ------ template int runLength(int N, T *arr, void *val_s = NULL, void *len_s = NULL){ int i, rN; T *val = (T*) val_s; int *len = (int*) len_s; if(N==0) return 0; if(val==NULL || len==NULL){ void *mem = wmem; if(val==NULL) walloc1d(&val, N, &mem); if(len==NULL) walloc1d(&len, N, &mem); } rN = 1; val[0] = arr[0]; len[0] = 1; rep(i,1,N){ if(val[rN-1] == arr[i]){ len[rN-1]++; } else { val[rN] = arr[i]; len[rN] = 1; rN++; } } return rN; } ------------------------------- arrcmp ------ template inline int arrcmp(int As, S A[], int Bs, T B[]){ int i; for(i=0;;i++){ if(i==As==Bs) break; if(i==As) return -1; if(i==Bs) return 1; if(A[i] < B[i]) return -1; if(A[i] > B[i]) return 1; } return 0; } ------------------------------- arrErase ------ template S arrErase(int k, int &sz, S a[]){ int i; S res; res = a[k]; sz--; rep(i,k,sz) a[i] = a[i+1]; return res; } template void arrErase(int k, int &sz, S a[], T b[]){ int i; sz--; rep(i,k,sz) a[i] = a[i+1]; rep(i,k,sz) b[i] = b[i+1]; } template void arrErase(int k, int &sz, S a[], T b[], U c[]){ int i; sz--; rep(i,k,sz) a[i] = a[i+1]; rep(i,k,sz) b[i] = b[i+1]; rep(i,k,sz) c[i] = c[i+1]; } ------------------------------- arrEraseVal1 ------ template inline int arrEraseVal_L(S val1, int &sz, S a[]){ int i, n = sz; sz = 0; rep(i,n) if(a[i]!=val1) a[sz++] = a[i]; return n - sz; } ------------------------------- arrEraseVal2 ------ template inline int arrEraseVal_L(S val1, S val2, int &sz, S a[]){ int i, n = sz; sz = 0; rep(i,n) if(a[i]!=val1 && a[i]!=val2) a[sz++] = a[i]; return n - sz; } ------------------------------- arrEraseVal3 ------ template inline int arrEraseVal_L(S val1, S val2, S val3, int &sz, S a[]){ int i, n = sz; sz = 0; rep(i,n) if(a[i]!=val1 && a[i]!=val2 && a[i]!=val3) a[sz++] = a[i]; return n - sz; } ------------------------------- arrEraseVal4 ------ template inline int arrEraseVal_L(S val1, S val2, S val3, S val4, int &sz, S a[]){ int i, n = sz; sz = 0; rep(i,n) if(a[i]!=val1 && a[i]!=val2 && a[i]!=val3 && a[i]!=val4) a[sz++] = a[i]; return n - sz; } ------------------------------- vecEraseVal1 ------ template inline int vecEraseVal_L(S val1, vector &a){ int i, k = 0, n = a.size(); rep(i,n) if(a[i]!=val1) a[k++] = a[i]; i = n - k; while(a.size() > k) a.pop_back(); return i; } ------------------------------- Mex ------ template int Mex_L(int n, T a[], int sorted = 0, void *mem = wmem){ int i, k = 0; if(sorted==0){ T *arr; walloc1d(&arr, n, &mem); rep(i,n) arr[i] = a[i]; sort(arr, arr+n); rep(i,n) if(arr[i]==k) k++; } else { rep(i,n) if(a[i]==k) k++; } return k; } ------------------------------- Mex1 ------ template inline int Mex_L(T x){ int k = 0; while(k==x) k++; return k; } ------------------------------- Mex2 ------ template inline int Mex_L(T1 x, T2 y){ int k = 0; while(k==x || k==y) k++; return k; } ------------------------------- Mex3 ------ template inline int Mex_L(int x, int y, int z){ int k = 0; while(k==x || k==y || k==z) k++; return k; } ------------------------------- Distinct ------ template int Distinct(int N, T A[], int sorted=0, void *mem = wmem){ int i, k, res = 1; T *a; if(N==0) return 0; if(sorted){ rep(i,1,N) if(A[i]!=A[i-1]) res++; } else { walloc1d(&a,N,&mem); rep(i,N) a[i] = A[i]; sort(a,a+N); rep(i,1,N) if(a[i]!=a[i-1]) res++; } return res; } template int Distinct(vector A, int sorted=0, void *mem = wmem){ int i, k, res = 1, N = A.size(); T *a; if(N==0) return 0; if(sorted){ rep(i,1,N) if(A[i]!=A[i-1]) res++; } else { walloc1d(&a,N,&mem); rep(i,N) a[i] = A[i]; sort(a,a+N); rep(i,1,N) if(a[i]!=a[i-1]) res++; } return res; } ------------------------------- DistinctE_2 ------ template inline int DistinctE_L(T1 a, T2 b){ if(a != b) return 2; return 1; } ------------------------------- DistinctE_3 ------ template inline int DistinctE_L(T1 a, T2 b, T3 c){ if(a==b){ if(a==c) return 1; return 2; } if(a==c || b==c) return 2; return 3; } ------------------------------- DistinctE_4 ------ template inline int DistinctE_L(T1 a, T2 b, T3 c, T4 d){ if(a==b){ if(a==c){ if(a==d) return 1; return 2; } if(a==d || c==d) return 2; return 3; } if(a==c){ if(a==d || b==d) return 2; return 3; } if(b==c){ if(a==d || b==d) return 2; return 3; } if(a==d || b==d || c==d) return 3; return 4; } ------------------------------- Count ------ template int Count(const int N, const T A[], const S val){ int res = 0; rep(i,N) if(A[i]==val) res++; return res; } template int Count(const vector &A, const S val){ int res = 0; rep(i,A.size()) if(A[i]==val) res++; return res; } template int Count(const string &A, const S val){ int res = 0; rep(i,A.size()) if(A[i]==val) res++; return res; } ------------------------------- arrCountVal ------ template int arrCountVal(const int N, const T A[], const S val){ int res = 0; rep(i,N) if(A[i]==val) res++; return res; } template int arrCountVal(const vector &A, const S val){ int res = 0; rep(i,A.size()) if(A[i]==val) res++; return res; } template int arrCountVal(const string &A, const S val){ int res = 0; rep(i,A.size()) if(A[i]==val) res++; return res; } ------------------------------- arrCountValSeqMax ------ template int arrCountValSeqMax(const int N, const T A[], const S val){ int res = 0, cur = 0; rep(i,N){ if(A[i]==val){ cur++; if(res < cur) res = cur; } else { cur = 0; } } return res; } template int arrCountValSeqMax(const string A, const S val){ int res = 0, cur = 0; rep(i,A.size()){ if(A[i]==val){ cur++; if(res < cur) res = cur; } else { cur = 0; } } return res; } ------------------------------- PalindromeCost ------ template int PalindromeCost(const int N, const T A[]){ int i, res = 0; rep(i,N/2) if(A[i] != A[N-1-i]) res++; return res; } template int PalindromeCost(const vector &A){ const int N = A.size(); int i, res = 0; rep(i,N/2) if(A[i] != A[N-1-i]) res++; return res; } int PalindromeCost(const string &A){ const int N = A.size(); int i, res = 0; rep(i,N/2) if(A[i] != A[N-1-i]) res++; return res; } ------------------------------- arrInsert ------ template inline void arrInsert(const int k, int &sz, S a[], const S aval){ int i; sz++; for(i=sz-1;i>k;i--) a[i] = a[i-1]; a[k] = aval; } template inline void arrInsert(const int k, int &sz, S a[], const S aval, T b[], const T bval){ int i; sz++; for(i=sz-1;i>k;i--) a[i] = a[i-1]; for(i=sz-1;i>k;i--) b[i] = b[i-1]; a[k] = aval; b[k] = bval; } template inline void arrInsert(const int k, int &sz, S a[], const S aval, T b[], const T bval, U c[], const U cval){ int i; sz++; for(i=sz-1;i>k;i--) a[i] = a[i-1]; for(i=sz-1;i>k;i--) b[i] = b[i-1]; for(i=sz-1;i>k;i--) c[i] = c[i-1]; a[k] = aval; b[k] = bval; c[k] = cval; } template inline void arrInsert(const int k, int &sz, S a[], const S aval, T b[], const T bval, U c[], const U cval, V d[], const V dval){ int i; sz++; for(i=sz-1;i>k;i--) a[i] = a[i-1]; for(i=sz-1;i>k;i--) b[i] = b[i-1]; for(i=sz-1;i>k;i--) c[i] = c[i-1]; for(i=sz-1;i>k;i--) d[i] = d[i-1]; a[k] = aval; b[k] = bval; c[k] = cval; d[k] = dval; } ------------------------------- floor_sum ------ ll floor_sum(ll n, ll m, ll a, ll b){ ll res = 0, s, t; if(m < 0){ m = -m; a = -a; b = -b; } t = fDiv(a, m); if(t){ res += (n-1) * n / 2 * t; a -= t * m; } t = fDiv(b, m); if(t){ res += n * t; b -= t * m; } for(;;){ s = (a * n + b) / m; if(s==0) break; t = s * m - b; res += (n - (t + a - 1) / a) * s; n = s; b = a - t % a; if(b == a) b = 0; swap(m,a); if(a >= m){ res += (n-1) * n / 2 * (a / m); a %= m; } if(b >= m){ res += n * (b / m); b %= m; } } return res; } ------------------------------- floor_sum2 ------ ll floor_sum2(ll a, ll k){ ll i = 1, j, v, res = 0; if(k > a) k = a; while(i <= k){ v = a / i; j = min(k, a / v) + 1; res += v * (j-i); i = j; } return res; } ll floor_sum2(ll a){ ll i = 1, j, v, res = 0; while(i <= a){ v = a / i; j = a / v + 1; res += v * (j-i); i = j; } return res; } ------------------------------- Comb ------ template struct Comb{ int mem_fact; T *factri, *ifactri; int mem_dfact; T *dfactri; int mem_pw2, mem_pw3, mem_pw10, mem_rep1; T *pw2c, *pw3c, *pw10c, *rep1c; int mem_ipw2, mem_ipw3, mem_ipw10; T *ipw2c, *ipw3c, *ipw10c; Comb(){ mem_fact = 0; mem_dfact = 0; mem_pw2 = mem_pw3 = mem_pw10 = mem_rep1 = 0; mem_ipw2 = mem_ipw3 = mem_ipw10 = 0; } inline void expand_fact(int k){ int i; if(k <= mem_fact) return; k >?= 2 * mem_fact; if(mem_fact == 0){ factri = (T*)malloc(k * sizeof(T)); ifactri = (T*)malloc(k * sizeof(T)); factri[0] = 1; rep(i,1,k) factri[i] = i * factri[i-1]; ifactri[k-1] = 1 / factri[k-1]; rrep(i,k-1) ifactri[i] = (i+1) * ifactri[i+1]; } else { factri = (T*)realloc(factri, k * sizeof(T)); ifactri = (T*)realloc(ifactri, k * sizeof(T)); rep(i,mem_fact,k) factri[i] = i * factri[i-1]; ifactri[k-1] = 1 / factri[k-1]; rrep(i,mem_fact,k-1) ifactri[i] = (i+1) * ifactri[i+1]; } mem_fact = k; } inline T fac(int k){ if(mem_fact < k+1) expand_fact(k+1); return factri[k]; } inline T ifac(int k){ if(mem_fact < k+1) expand_fact(k+1); return ifactri[k]; } inline T C(int a, int b){ if(b < 0 || b > a) return 0; if(mem_fact < a+1) expand_fact(a+1); return factri[a] * ifactri[b] * ifactri[a-b]; } inline T P(int a, int b){ if(b < 0 || b > a) return 0; if(mem_fact < a+1) expand_fact(a+1); return factri[a] * ifactri[a-b]; } inline T H(int a, int b){ if(a==0 && b==0) return 1; if(a <= 0 || b < 0) return 0; if(mem_fact < a+b) expand_fact(a+b); return C(a+b-1, b); } inline T Multinomial(int sz, int a[]){ int i, s = 0; T res; rep(i,sz) s += a[i]; if(mem_fact < s+1) expand_fact(s+1); res = factri[s]; rep(i,sz) res *= ifactri[a[i]]; return res; } inline T Multinomial(int a){ return 1; } inline T Multinomial(int a, int b){ if(mem_fact < a+b+1) expand_fact(a+b+1); return factri[a+b] * ifactri[a] * ifactri[b]; } inline T Multinomial(int a, int b, int c){ if(mem_fact < a+b+c+1) expand_fact(a+b+c+1); return factri[a+b+c] * ifactri[a] * ifactri[b] * ifactri[c]; } inline T Multinomial(int a, int b, int c, int d){ if(mem_fact < a+b+c+d+1) expand_fact(a+b+c+d+1); return factri[a+b+c+d] * ifactri[a] * ifactri[b] * ifactri[c] * ifactri[d]; } inline T Catalan(int n){ if(n < 0) return 0; if(mem_fact < 2*n+1) expand_fact(2*n+1); return factri[2*n] * ifactri[n] * ifactri[n+1]; } inline T Catalan(int n, int m, int k){ if(k <= 0) return C(n+m, n); if(n < k || m < k) return 0; return C(n+m, m) - C(n+m, k-1); } inline T Catalan_s(ll n, ll m, ll k){ if(k <= 0) return C_s(n+m, n); if(n < k || m < k) return 0; return C_s(n+m, m) - C_s(n+m, k-1); } inline T C_s(ll a, ll b){ ll i; T res; if(b < 0 || b > a) return 0; if(b > a - b) b = a - b; res = 1; rep(i,b){ res *= a - i; res /= i + 1; } return res; } inline T P_s(ll a, ll b){ ll i; T res; if(b < 0 || b > a) return 0; res = 1; rep(i,b) res *= a - i; return res; } inline T H_s(ll a, ll b){ if(a==0 && b==0) return 1; if(a <= 0 || b < 0) return 0; return C_s(a+b-1, b); } inline T per_s(ll n, ll k){ T d; int m; if(n < 0 || k < 0) return 0; if(n == k == 0) return 1; if(n == 0 || k == 0) return 0; if(k==1) return 1; if(k==2){ d = n / 2; return d; } if(k==3){ d = (n-1) / 6; m = (n-1) % 6; if(m==0) return 3 * d * d + d; if(m==1) return 3 * d * d + 2 * d; if(m==2) return 3 * d * d + 3 * d + 1; if(m==3) return 3 * d * d + 4 * d + 1; if(m==4) return 3 * d * d + 5 * d + 2; if(m==5) return 3 * d * d + 6 * d + 3; } assert(0 && "per_s should be k <= 3"); return -1; } inline void expand_dfact(int k){ int i; if(k <= mem_dfact) return; k >?= 3; k >?= 2 * mem_dfact; if(mem_dfact==0){ dfactri = (T*)malloc(k * sizeof(T)); dfactri[0] = dfactri[1] = 1; rep(i,2,k) dfactri[i] = i * dfactri[i-2]; } else { dfactri = (T*)realloc(dfactri, k * sizeof(T)); rep(i,mem_dfact,k) dfactri[i] = i * dfactri[i-2]; } mem_dfact = k; } inline void expand_pw2(int k){ int i; if(k <= mem_pw2) return; k >?= 2 * mem_pw2; if(mem_pw2==0){ pw2c = (T*)malloc(k * sizeof(T)); pw2c[0] = 1; rep(i,1,k) pw2c[i] = 2 * pw2c[i-1]; } else { pw2c = (T*)realloc(pw2c, k * sizeof(T)); rep(i,mem_pw2,k) pw2c[i] = 2 * pw2c[i-1]; } mem_pw2 = k; } inline void expand_ipw2(int k){ int i; if(k <= mem_ipw2) return; k >?= 2; k >?= 2 * mem_ipw2; if(mem_ipw2==0){ ipw2c = (T*)malloc(k * sizeof(T)); ipw2c[0] = 1; ipw2c[1] = ipw2c[0] / 2; rep(i,1,k) ipw2c[i] = ipw2c[1] * ipw2c[i-1]; } else { ipw2c = (T*)realloc(ipw2c, k * sizeof(T)); rep(i,mem_ipw2,k) ipw2c[i] = ipw2c[1] * ipw2c[i-1]; } mem_ipw2 = k; } inline void expand_pw3(int k){ int i; if(k <= mem_pw3) return; k >?= 2 * mem_pw3; if(mem_pw3==0){ pw3c = (T*)malloc(k * sizeof(T)); pw3c[0] = 1; rep(i,1,k) pw3c[i] = 3 * pw3c[i-1]; } else { pw3c = (T*)realloc(pw3c, k * sizeof(T)); rep(i,mem_pw3,k) pw3c[i] = 3 * pw3c[i-1]; } mem_pw3 = k; } inline void expand_ipw3(int k){ int i; if(k <= mem_ipw3) return; k >?= 2; k >?= 2 * mem_ipw3; if(mem_ipw3==0){ ipw3c = (T*)malloc(k * sizeof(T)); ipw3c[0] = 1; ipw3c[1] = ipw3c[0] / 3; rep(i,1,k) ipw3c[i] = ipw3c[1] * ipw3c[i-1]; } else { ipw3c = (T*)realloc(ipw3c, k * sizeof(T)); rep(i,mem_ipw3,k) ipw3c[i] = ipw3c[1] * ipw3c[i-1]; } mem_ipw3 = k; } inline void expand_pw10(int k){ int i; if(k <= mem_pw10) return; k >?= 2 * mem_pw10; if(mem_pw10==0){ pw10c = (T*)malloc(k * sizeof(T)); pw10c[0] = 1; rep(i,1,k) pw10c[i] = 10 * pw10c[i-1]; } else { pw10c = (T*)realloc(pw10c, k * sizeof(T)); rep(i,mem_pw10,k) pw10c[i] = 10 * pw10c[i-1]; } mem_pw10 = k; } inline void expand_ipw10(int k){ int i; if(k <= mem_ipw10) return; k >?= 2; k >?= 2 * mem_ipw10; if(mem_ipw10==0){ ipw10c = (T*)malloc(k * sizeof(T)); ipw10c[0] = 1; ipw10c[1] = ipw10c[0] / 10; rep(i,1,k) ipw10c[i] = ipw10c[1] * ipw10c[i-1]; } else { ipw10c = (T*)realloc(ipw10c, k * sizeof(T)); rep(i,mem_ipw10,k) ipw10c[i] = ipw10c[1] * ipw10c[i-1]; } mem_ipw10 = k; } inline void expand_rep1(int k){ int i; if(k <= mem_rep1) return; k >?= 2 * mem_rep1; if(mem_rep1==0){ rep1c = (T*)malloc(k * sizeof(T)); rep1c[0] = 0; rep(i,1,k) rep1c[i] = 10 * rep1c[i-1] + 1; } else { rep1c = (T*)realloc(rep1c, k * sizeof(T)); rep(i,mem_rep1,k) rep1c[i] = 10 * rep1c[i-1] + 1; } mem_rep1 = k; } inline T dfac(int k){ if(k >= 0){ if(mem_dfact < k+1) expand_dfact(k+1); return dfactri[k]; } if(k==-1) return 1; k = - k - 2; if(k % 4 == 1) return 1 / (-dfac(k)); return 1 / dfac(k); } inline T pw2(int k){ if(k >= 0){ if(mem_pw2 < k+1) expand_pw2(k+1); return pw2c[k]; } else { k = -k; if(mem_ipw2 < k+1) expand_ipw2(k+1); return ipw2c[k]; } } inline T pw3(int k){ if(k >= 0){ if(mem_pw3 < k+1) expand_pw3(k+1); return pw3c[k]; } else { k = -k; if(mem_ipw3 < k+1) expand_ipw3(k+1); return ipw3c[k]; } } inline T pw10(int k){ if(k >= 0){ if(mem_pw10 < k+1) expand_pw10(k+1); return pw10c[k]; } else { k = -k; if(mem_ipw10 < k+1) expand_ipw10(k+1); return ipw10c[k]; } } inline T repunit(int k){ if(mem_rep1 < k+1) expand_rep1(k+1); return rep1c[k]; } }; ------------------------------- Comb_Cs_Modint ------ template<> inline Modint Comb::C_s(ll a, ll b){ ll i; Modint res, d; if(b < 0 || b > a) return 0; if(b > a - b) b = a - b; res = d = 1; rep(i,b){ res *= a - i; d *= i + 1; } return res / d; } ------------------------------- Comb_Cs_modint ------ template<> inline modint Comb::C_s(ll a, ll b){ ll i; modint res, d; if(b < 0 || b > a) return 0; if(b > a - b) b = a - b; res = d = 1; rep(i,b){ res *= a - i; d *= i + 1; } return res / d; } ------------------------------- Comb_Cs_Mint ------ template<> inline Mint Comb::C_s(ll a, ll b){ ll i; Mint res, d; if(b < 0 || b > a) return 0; if(b > a - b) b = a - b; res = d = 1; rep(i,b){ res *= a - i; d *= i + 1; } return res / d; } ------------------------------- Comb_Cs_mint ------ template<> inline mint Comb::C_s(ll a, ll b){ ll i; mint res, d; if(b < 0 || b > a) return 0; if(b > a - b) b = a - b; res = d = 1; rep(i,b){ res *= a - i; d *= i + 1; } return res / d; } ------------------------------- arrRot ------ template void arrRot(int k, int N, T A[], T B[] = NULL, void *mem = wmem){ int fg = 0; k %%= N; if(B==NULL){ walloc1d(&B, N, &mem); fg = 1; } rep(i,k,N) B[i-k] = A[i]; rep(i,k) B[N-k+i] = A[i]; if(fg) rep(i,N) A[i] = B[i]; } ------------------------------- Polynomial ------ template struct Polynomial { int d, mem; T *c; Polynomial(){ mem = 1; c = new T[mem]; d = 0; c[0] = 0; } Polynomial(T a){ mem = 1; c = new T[mem]; d = 0; c[0] = a; } Polynomial(const Polynomial &a){ d = a.d; mem = d + 1; c = new T[mem]; rep(i,d+1) c[i] = a.c[i]; } ~Polynomial(){ delete [] c; } void expand(int z){ T *cc; if(z <= mem) return; mem = max(z, 2 * mem); cc = new T[mem]; rep(i,d+1) cc[i] = c[i]; delete [] c; c = cc; } inline void change(const int dg, const T cf){ expand(dg+1); while(d < dg) c[++d] = 0; c[dg] = cf; while(d && c[d]==0) d--; } inline int deg(void){ return d; } inline T coef(const int k){ if(k > d) return 0; return c[k]; } Polynomial& operator=(const T a){ d = 0; expand(d + 1); c[0] = a; return *this; } Polynomial& operator=(const Polynomial &a){ int i; d = a.d; expand(d + 1); rep(i,d+1) c[i] = a.c[i]; return *this; } Polynomial& operator+=(const Polynomial &a){ int i, k; k = max(d, a.d); expand(k+1); while(d < k) c[++d] = 0; rep(i,a.d+1) c[i] += a.c[i]; while(d && c[d]==0) d--; return *this; } Polynomial operator+(const Polynomial &a){ return Polynomial(*this) += a; } Polynomial& operator-=(const Polynomial &a){ int i, k; k = max(d, a.d); expand(k+1); while(d < k) c[++d] = 0; rep(i,a.d+1) c[i] -= a.c[i]; while(d && c[d]==0) d--; return *this; } Polynomial operator-(const Polynomial &a){ return Polynomial(*this) -= a; } Polynomial& operator*=(const Polynomial &a){ int i, j, k; T *cc; void *mem = wmem; k = d + a.d; expand(k+1); walloc1d(&cc, k+1, &mem); rep(i,k+1) cc[i] = 0; rep(i,d+1) rep(j,a.d+1) cc[i+j] += c[i] * a.c[j]; rep(i,k+1) c[i] = cc[i]; d = k; while(d && c[d]==0) d--; return *this; } Polynomial operator*(const Polynomial &a){ return Polynomial(*this) *= a; } Polynomial& operator/=(const Polynomial &a){ int i, j, k; T *cc, e; void *mem = wmem; walloc1d(&cc, d-a.d, &mem); for(i=d; i>=a.d; i--){ cc[i-a.d] = e = c[i] / a.c[a.d]; rep(j, a.d+1) c[i-j] -= e * a.c[a.d-j]; } d -= a.d; rep(i,d+1) c[i] = cc[i]; return *this; } Polynomial operator/(const Polynomial &a){ return Polynomial(*this) /= a; } Polynomial& operator%=(const Polynomial &a){ int i, j, k; T *cc, e; void *mem = wmem; walloc1d(&cc, d-a.d, &mem); for(i=d; i>=a.d; i--){ cc[i-a.d] = e = c[i] / a.c[a.d]; rep(j, a.d+1) c[i-j] -= e * a.c[a.d-j]; } while(d && c[d]==0) d--; return *this; } Polynomial operator%(const Polynomial &a){ return Polynomial(*this) %= a; } Polynomial& operator*=(const T &a){ rep(i,d+1) c[i] *= a; while(d && c[d]==0) d--; return *this; } Polynomial operator*(const T &a){ return Polynomial(*this) *= a; } Polynomial& operator/=(const T &a){ rep(i,d+1) c[i] /= a; while(d && c[d]==0) d--; return *this; } Polynomial operator/(const T &a){ return Polynomial(*this) /= a; } inline T operator()(const T x){ int i; T res; res = 0; for(i=d;i>=0;i--) res = res * x + c[i]; return res; } }; template Polynomial operator*(const T a, const Polynomial &b){return Polynomial(b)*=a;} ------------------------------- SuffixArray ------ template void SuffixArray(T *s, int N, int K, int *SA, int *LCP = NULL, void *mem = wmem) { int i, j, d, m, *s1; int name, prev, pos; char *t, *lms; int *cnt, *cnt1, *cnt2; walloc1d(&t, N+1, &mem); walloc1d(&lms, N+1, &mem); walloc1d(&cnt, K+1, &mem); walloc1d(&cnt1, K+1, &mem); walloc1d(&cnt2, K+1, &mem); N++; s[N-1] = 0; t[N-1] = 1; t[N-2] = 0; for(i=N-3;i>=0;i--){ if(s[i] < s[i+1] || (s[i]==s[i+1] && t[i+1])) t[i] = 1; else t[i] = 0; } lms[0] = 0; REP(i,1,N){ if(t[i] && !t[i-1]) lms[i] = 1; else lms[i] = 0; } rep(i,K+1) cnt1[i] = 0; rep(i,N) cnt1[s[i]]++; j = 0; rep(i,K+1){ j += cnt1[i]; cnt2[i] = j - cnt1[i]; cnt1[i] = j; } rep(i,K+1) cnt[i] = cnt1[i]; for(i=0; i=0 && !t[j]) SA[cnt[s[j]]++] = j; } rep(i,K+1) cnt[i] = cnt1[i]; for(i=N-1;i>=0;i--){ j = SA[i] - 1; if(j>=0 && t[j]) SA[--cnt[s[j]]] = j; } m = 0; rep(i,N) if(lms[SA[i]]) SA[m++] = SA[i]; REP(i,m,N) SA[i] = -1; name=0; prev=-1; rep(i,m){ pos = SA[i]; rep(d,N){ if(prev==-1 || s[pos+d]!=s[prev+d] || t[pos+d]!=t[prev+d]){ name++; prev=pos; break; } else if(d>0 && (lms[pos+d] || lms[prev+d])){ break; } } pos /= 2; SA[m+pos]=name-1; } for(i=N-1, j=N-1; i>=m; i--) if(SA[i]>=0) SA[j--]=SA[i]; s1 = SA+N-m; if(name=0; i--) { j=SA[i]; SA[i]=-1; SA[--cnt[s[j]]]=j; } rep(i,N){ j = SA[i]-1; if(j>=0 && !t[j]) SA[cnt2[s[j]]++] = j; } for(i=N-1;i>=0;i--){ j = SA[i] - 1; if(j>=0 && t[j]) SA[--cnt1[s[j]]] = j; } if(LCP != NULL){ cnt = (int*)t; d = 0; rep(i,N) cnt[SA[i]] = i; rep(i,N){ if(cnt[i]){ for(j=SA[cnt[i]-1]; j+d0) d--; } } } ------------------------------- unionFind ------ struct unionFind{ int *d, N, M; unionFind(){} unionFind(const char mode, const int n, void **mem = &wmem){ assert(mode == 'm' || mode == 'w'); if(mode == 'm') malloc(n); if(mode == 'w') walloc(n, mem); } unionFind(const char mode, const int n, const int fg, void **mem = &wmem){ assert(mode == 'm' || mode == 'w'); if(mode == 'm') malloc(n, fg); if(mode == 'w') walloc(n, fg, mem); } inline void malloc(const int n){ d = (int*)std::malloc(n*sizeof(int)); M = n; } inline void malloc(const int n, const int fg){ d = (int*)std::malloc(n*sizeof(int)); M = n; if(fg) init(n); } inline void free(void){ std::free(d); } inline void walloc(const int n, void **mem=&wmem){ walloc1d(&d, n, mem); M = n; } inline void walloc(const int n, const int fg, void **mem=&wmem){ walloc1d(&d, n, mem); M = n; if(fg) init(n); } inline void init(const int n){ int i; N = n; rep(i,n) d[i] = -1; } inline void init(void){ init(M); } inline int get(int a){ int t = a, k; while(d[t]>=0) t=d[t]; while(d[a]>=0) k=d[a], d[a]=t, a=k; return a; } inline int connect(int a, int b){ if(d[a]>=0) a=get(a); if(d[b]>=0) b=get(b); if(a==b) return 0; if(d[a] < d[b]) d[a] += d[b], d[b] = a; else d[b] += d[a], d[a] = b; return 1; } inline int operator()(int a){ return get(a); } inline int operator()(int a, int b){ return connect(a,b); } inline int& operator[](const int a){ return d[a]; } inline int size(int a){ a = get(a); return -d[a]; } inline int sizeList(int res[]){ int i, sz=0; rep(i,N) if(d[i]<0) res[sz++] = -d[i]; return sz; } inline int comp(int res[], void *mem = wmem){ int i, sz=0; int *cnt; walloc1d(&cnt, N, &mem); rep(i,N) cnt[i] = 0; rep(i,N) cnt[get(i)] = 1; rep(i,N) if(cnt[i]) cnt[i] = sz++; rep(i,N) res[i] = cnt[get(i)]; return sz; } }; ------------------------------- weightedUnionFind ------ template struct weightedUnionFind{ int *d, N, M; T *w; weightedUnionFind(){} weightedUnionFind(const char mode, const int n, void **mem = &wmem){ assert(mode == 'm' || mode == 'w'); if(mode == 'm') malloc(n); if(mode == 'w') walloc(n, mem); } weightedUnionFind(const char mode, const int n, const int fg, void **mem = &wmem){ assert(mode == 'm' || mode == 'w'); if(mode == 'm') malloc(n, fg); if(mode == 'w') walloc(n, fg, mem); } inline void malloc(const int n){ d = (int*)std::malloc(n*sizeof(int)); w = (T*)std::malloc(n*sizeof(T)); M = n; } inline void malloc(const int n, const int fg){ d = (int*)std::malloc(n*sizeof(int)); w = (T*)std::malloc(n*sizeof(T)); M = n; if(fg) init(n); } inline void free(void){ std::free(d); } inline void walloc(const int n, void **mem=&wmem){ walloc1d(&d, n, mem); walloc1d(&w, n, mem); M = n; } inline void walloc(const int n, const int fg, void **mem=&wmem){ walloc1d(&d, n, mem); walloc1d(&w, n, mem); M = n; if(fg) init(n); } inline void init(const int n){ int i; N = n; rep(i,n) d[i] = -1; rep(i,n) w[i] = 0; } inline void init(void){ init(M); } inline int get(int a){ int t = a, k; T s, m; s = 0; while(d[t]>=0) s+=w[t], t=d[t]; while(d[a]>=0) k=d[a], m=w[a], d[a]=t, w[a]=s, a=k, s-=m; return a; } inline int connect(int a, int b, T c){ if(d[a]>=0) get(a), c += w[a], a = get(a); if(d[b]>=0) get(b), c -= w[b], b = get(b); if(a==b) return 0; if(d[a] < d[b]) d[a] += d[b], d[b] = a, w[b] = c; else d[b] += d[a], d[a] = b, w[a] = -c; return 1; } inline T diff(int a, int b){ get(a); get(b); return w[b]-w[a]; } inline int operator()(int a){ return get(a); } inline int operator()(int a, int b, T c){ return connect(a,b,c); } inline int& operator[](const int a){ return d[a]; } inline int size(int a){ a = get(a); return -d[a]; } inline int sizeList(int res[]){ int i, sz=0; rep(i,N) if(d[i]<0) res[sz++] = -d[i]; return sz; } inline int comp(int res[], void *mem = wmem){ int i, sz=0; int *cnt; walloc1d(&cnt, N, &mem); rep(i,N) cnt[i] = 0; rep(i,N) cnt[get(i)] = 1; rep(i,N) if(cnt[i]) cnt[i] = sz++; rep(i,N) res[i] = cnt[get(i)]; return sz; } }; ------------------------------- rollbackUnionFind ------ struct rollbackUnionFind{ int *d, N, M; int *h1, *h2, sz, snapsz; rollbackUnionFind(){} rollbackUnionFind(const char mode, const int n, void **mem = &wmem){ assert(mode == 'm' || mode == 'w'); if(mode == 'm') malloc(n); if(mode == 'w') walloc(n, mem); } rollbackUnionFind(const char mode, const int n, const int fg, void **mem = &wmem){ assert(mode == 'm' || mode == 'w'); if(mode == 'm') malloc(n, fg); if(mode == 'w') walloc(n, fg, mem); } inline void malloc(const int n){ d = (int*)std::malloc(n*sizeof(int)); h1 = (int*)std::malloc(2*n*sizeof(int)); h2 = (int*)std::malloc(2*n*sizeof(int)); M = n; } inline void malloc(const int n, const int fg){ d = (int*)std::malloc(n*sizeof(int)); h1 = (int*)std::malloc(2*n*sizeof(int)); h2 = (int*)std::malloc(2*n*sizeof(int)); M = n; if(fg) init(n); } inline void free(void){ std::free(d); std::free(h1); std::free(h2); } inline void walloc(const int n, void **mem=&wmem){ walloc1d(&d, n, mem); walloc1d(&h1, 2*n, mem); walloc1d(&h2, 2*n, mem); M = n; } inline void walloc(const int n, const int fg, void **mem=&wmem){ walloc1d(&d, n, mem); walloc1d(&h1, 2*n, mem); walloc1d(&h2, 2*n, mem); M = n; if(fg) init(n); } inline void init(const int n){ int i; N = n; rep(i,n) d[i] = -1; sz = 0; snapsz = 0; } inline void init(void){ init(M); } inline int get(int a){ while(d[a]>=0) a=d[a]; return a; } inline int connect(int a, int b){ if(d[a]>=0) a=get(a); if(d[b]>=0) b=get(b); if(a==b) return 0; h1[sz] = a; h2[sz] = d[a]; sz++; h1[sz] = b; h2[sz] = d[b]; sz++; if(d[a] < d[b]) d[a] += d[b], d[b] = a; else d[b] += d[a], d[a] = b; return 1; } inline int operator()(int a){ return get(a); } inline int operator()(int a, int b){ return connect(a,b); } inline int& operator[](const int a){ return d[a]; } inline int size(int a){ a = get(a); return -d[a]; } inline int sizeList(int res[]){ int i, sz=0; rep(i,N) if(d[i]<0) res[sz++] = -d[i]; return sz; } inline int comp(int res[], void *mem = wmem){ int i, sz=0; int *cnt; walloc1d(&cnt, N, &mem); rep(i,N) cnt[i] = 0; rep(i,N) cnt[get(i)] = 1; rep(i,N) if(cnt[i]) cnt[i] = sz++; rep(i,N) res[i] = cnt[get(i)]; return sz; } inline int undo(void){ if(sz==0) return 0; sz--; d[h1[sz]] = h2[sz]; sz--; d[h1[sz]] = h2[sz]; if(snapsz > sz) snapsz = sz; return 1; } inline void snapshot(void){ snapsz = sz; } inline void rollback(void){ while(snapsz < sz){ sz--; d[h1[sz]] = h2[sz]; sz--; d[h1[sz]] = h2[sz]; } } }; ------------------------------- fibonacci_mod ------ int fibonacci_mod_L(ull n, int md){ ull a=1, b=0, ma=0, mb=1, ta, tb; while(n){ if(n%2){ ta = a*ma + b*mb; tb = a*mb + b*(ma+mb); a = ta % md; b = tb % md; } ta = ma*ma + mb*mb; tb = (ma*2 + mb)*mb; ma = ta % md; mb = tb % md; n/=2; } return b; } ------------------------------- Fibonacci_mod ------ int Fibonacci_mod(ull n){ ull a=1, b=0, ma=0, mb=1, ta, tb; while(n){ if(n%2){ ta = a*ma + b*mb; tb = a*mb + b*(ma+mb); a = ta % MD; b = tb % MD; } ta = ma*ma + mb*mb; tb = (ma*2 + mb)*mb; ma = ta % MD; mb = tb % MD; n/=2; } return b; } ------------------------------- Fib_mod ------ ull Fib_mod_L_ma[64], Fib_mod_L_mb[64]; void Fib_mod_init(){ int i; Fib_mod_L_ma[0] = 0; Fib_mod_L_mb[0] = 1; rep(i,1,64){ Fib_mod_L_ma[i] = (Fib_mod_L_ma[i-1]*Fib_mod_L_ma[i-1] + Fib_mod_L_mb[i-1]*Fib_mod_L_mb[i-1])%MD; Fib_mod_L_mb[i] = ((Fib_mod_L_ma[i-1]*2 + Fib_mod_L_mb[i-1]) * Fib_mod_L_mb[i-1])%MD; } } int Fib_mod(ull n){ int i = 0; ull a=1, b=0, ta, tb; while(n){ if(n%2){ ta = a*Fib_mod_L_ma[i] + b*Fib_mod_L_mb[i]; tb = a*Fib_mod_L_mb[i] + b*(Fib_mod_L_ma[i]+Fib_mod_L_mb[i]); a = ta % MD; b = tb % MD; } i++; n/=2; } return b; } ------------------------------- Fib_mod_init ------ {Fib_mod_init();} ------------------------------- get_inv_mod ------ int get_inv_mod(ll a, int md){ ll t = a, s = md, u = 1, v = 0, e; while(s){ e = t/s; t -= e*s; u -= e*v; swap(t,s); swap(u,v); } if(u<0) u += md; return u; } ------------------------------- extendedEuclid ------ void extendedEuclid(ll a, ll b, ll &x, ll &y, ll &z){ ll d=1, e=0, f, g=0, h=1, i, m, q, aa = a, bb = b; if(a==0 && b==0){ x = y = z = 0; return; } while(b){ q=a/b; m=a%b; f=d-q*e; i=g-q*h; a=b; b=m; d=e; e=f; g=h; h=i; } if(a < 0){ d = -d; g = -g; a = -a; } if(a != 1){ aa /= a; bb /= a; } if(d < 0 && bb > 0){ d += bb; g -= aa; } if(d < 0 && bb < 0){ d -= bb; g += aa; } x=d; y=g; z=a; } void extendedEuclid(ll a, ll b, ll &x, ll &y){ ll d=1, e=0, f, g=0, h=1, i, m, q, aa = a, bb = b; if(a==0 && b==0){ x = y = 0; return; } while(b){ q=a/b; m=a%b; f=d-q*e; i=g-q*h; a=b; b=m; d=e; e=f; g=h; h=i; } if(a < 0){ d = -d; g = -g; a = -a; } if(a != 1){ aa /= a; bb /= a; } if(d < 0 && bb > 0){ d += bb; g -= aa; } if(d < 0 && bb < 0){ d -= bb; g += aa; } x=d; y=g; } ------------------------------- chineseRemainder ------ ll chineseRemainder(int sz, ll val[], ll md[]){ int i; ll r = 0, m = 1, rn, mn, a, b, c, u, v; rep(i,sz){ rn = val[i]; mn = md[i]; if(rn < 0 || rn >= mn) rn %= mn; if(rn < 0) rn += mn; if(m < mn){ swap(r, rn); swap(m, mn); } if(m % mn == 0){ if(r % mn != rn) return -1; continue; } extendedEuclid(m, mn, a, b, c); u = mn / c; if((rn-r)%c) return -1; v = (rn - r) / c % u * a % u; r += v * m; m *= mn / c; if(r < 0) r += m; } return r; } ------------------------------- Cmod2 ------ template inline int Cmod2(T n, T k){ if((n&k)==k) return 1; return 0; } ------------------------------- Isqrt_f ------ inline ll Isqrt_f_L(const ll n){ ll r = sqrt(n); r = max(r-2, 0); while( (r+1)**2 <= n ) r++; return r; } ------------------------------- Isqrt_c ------ inline ll Isqrt_c_L(const ll n){ ll r = sqrt(n); r = max(r-2, 0); while( r**2 < n ) r++; return r; } ------------------------------- Isqrt_s ------ inline ll Isqrt_s_L(const ll n){ ll r = sqrt(n); r = max(r-2, 0); while( (r+1)**2 <= n ) r++; if(r*r!=n) r = -1; return r; } ------------------------------- Icbrt_f ------ inline ll Icbrt_f_L(const ll n){ ll r = pow(n, 1.0/3); r = max(r-2, 0); while( (r+1)**3 <= n ) r++; return r; } ------------------------------- Icbrt_c ------ inline ll Icbrt_c_L(const ll n){ ll r = pow(n, 1.0/3); r = max(r-2, 0); while( r**3 < n ) r++; return r; } ------------------------------- Icbrt_s ------ inline ll Icbrt_s_L(const ll n){ ll r = pow(n, 1.0/3); r = max(r-2, 0); while( (r+1)**3 <= n ) r++; if(r**3!=n) r = -1; return r; } ------------------------------- Iroot_f ------ inline ll Iroot_f_L(const ll N, const ll k){ ll res; if(N<=0) return 0; if(k==1) return N; if(k==2) return Isqrt_f(N); if(k==3) return Icbrt_f(N); if(k>=64) return 1; if(k>=40){ if((1LL< 0) res--; if( ((double)res+1)**k < 9.2233e18 && (res+1)**k <= N ) res++; if( ((double)res+1)**k < 9.2233e18 && (res+1)**k <= N ) res++; return res; } ------------------------------- Iroot_c ------ inline ll Iroot_c_L(const ll N, const ll k){ ll res; if(N<=0) return 0; if(N==1) return 1; if(k==1) return N; if(k==2) return Isqrt_c(N); if(k==3) return Icbrt_c(N); if(k>=64) return 1; if(k>=40){ if((1LL<=64) return 1; if(k>=40){ if((1LL< 9.2233e18 || res**k != N) return -1; return res; } ------------------------------- Unique ------ template void Unique(int &N, T A[], int sorted=0, void *mwm = wmem){ int i, k; if(!sorted) sortA(N, A); k = 0; rep(i,N) if(k==0 || A[k-1]!=A[i]) A[k++] = A[i]; N = k; } template void Unique(int &N, T A[], S B[], int sorted=0, void *mem = wmem){ int i, k = 0; if(!sorted) sortA(N, A, B, mem); rep(i,N){ if(!k || A[k-1]!=A[i]){ A[k] = A[i]; B[k] = B[i]; k++; } else { B[k-1] += B[i]; } } N=k; } ------------------------------- coordcomp_1 ------ template int coordcomp_L(int n, T arr[], void *mem = wmem){ int i, k = 0; T *r; int *ind; walloc1d(&r, n, &mem); walloc1d(&ind, n, &mem); rep(i,n) r[i] = arr[i]; rep(i,n) ind[i] = i; sortA(n, r, ind, mem); rep(i,n){ if(i && r[i] != r[i-1]) k++; arr[ind[i]] = k; } return k+1; } template int coordcomp_L(int n, T arr[], S res[], void *mem = wmem){ int i, k = 0; T *r; int *ind; walloc1d(&r, n, &mem); walloc1d(&ind, n, &mem); rep(i,n) r[i] = arr[i]; rep(i,n) ind[i] = i; sortA(n, r, ind, mem); rep(i,n){ if(i && r[i] != r[i-1]) k++; res[ind[i]] = k; } return k+1; } template int coordcomp_L(int n, const T arr[], S res[], void *mem = wmem){ int i, k = 0; T *r; int *ind; walloc1d(&r, n, &mem); walloc1d(&ind, n, &mem); rep(i,n) r[i] = arr[i]; rep(i,n) ind[i] = i; sortA(n, r, ind, mem); rep(i,n){ if(i && r[i] != r[i-1]) k++; res[ind[i]] = k; } return k+1; } ------------------------------- coordcomp_2 ------ template int coordcomp_L(int n1, T arr1[], int n2, T arr2[], void *mem = wmem){ int i, k = 0; T *r; int *ind; walloc1d(&r, n1+n2, &mem); walloc1d(&ind, n1+n2, &mem); rep(i,n1) r[i] = arr1[i]; rep(i,n2) r[n1+i] = arr2[i]; rep(i,n1+n2) ind[i] = i; sortA(n1+n2, r, ind, mem); rep(i,n1+n2){ if(i && r[i] != r[i-1]) k++; if(ind[i] < n1){ arr1[ind[i]] = k; } else { arr2[ind[i]-n1] = k; } } return k+1; } template int coordcomp_L(int n1, const T arr1[], int n2, const T arr2[], S1 res1[], S2 res2[], void *mem = wmem){ int i, k = 0; T *r; int *ind; walloc1d(&r, n1+n2, &mem); walloc1d(&ind, n1+n2, &mem); rep(i,n1) r[i] = arr1[i]; rep(i,n2) r[n1+i] = arr2[i]; rep(i,n1+n2) ind[i] = i; sortA(n1+n2, r, ind, mem); rep(i,n1+n2){ if(i && r[i] != r[i-1]) k++; if(ind[i] < n1){ res1[ind[i]] = k; } else { res2[ind[i]-n1] = k; } } return k+1; } ------------------------------- coordcomp_3 ------ template int coordcomp_L(int n1, T arr1[], int n2, T arr2[], int n3, T arr3[], void *mem = wmem){ int i, k = 0, nn = n1 + n2 + n3; T *r; int *ind; walloc1d(&r, nn, &mem); walloc1d(&ind, nn, &mem); rep(i,n1) r[i] = arr1[i]; rep(i,n2) r[n1+i] = arr2[i]; rep(i,n3) r[n1+n2+i] = arr3[i]; rep(i,nn) ind[i] = i; sortA(nn, r, ind, mem); rep(i,nn){ if(i && r[i] != r[i-1]) k++; if(ind[i] < n1){ arr1[ind[i]] = k; } else if(ind[i] < n1+n2){ arr2[ind[i]-n1] = k; } else { arr3[ind[i]-n1-n2] = k; } } return k+1; } template int coordcomp_L(int n1, const T arr1[], int n2, const T arr2[], int n3, const T arr3[], S1 res1[], S2 res2[], S3 res3[], void *mem = wmem){ int i, k = 0, nn = n1 + n2 + n3; T *r; int *ind; walloc1d(&r, nn, &mem); walloc1d(&ind, nn, &mem); rep(i,n1) r[i] = arr1[i]; rep(i,n2) r[n1+i] = arr2[i]; rep(i,n3) r[n1+n2+i] = arr3[i]; rep(i,nn) ind[i] = i; sortA(nn, r, ind, mem); rep(i,nn){ if(i && r[i] != r[i-1]) k++; if(ind[i] < n1){ res1[ind[i]] = k; } else if(ind[i] < n1+n2){ res2[ind[i]-n1] = k; } else { res3[ind[i]-n1-n2] = k; } } return k+1; } ------------------------------- Heap ------ template struct Heap { int size; T *val; void malloc(const int N){ val = (T*) std::malloc(N*sizeof(T)); size = 0; } void walloc(const int N, void **mem = &wmem){ walloc1d(&val, N, mem); size = 0; } void free(){ std::free(val); } void init(){ size = 0; } void up(){ int n = size - 1, m; while(n){ m = (n-1) / 2; if(val[m] <= val[n]) break; swap(val[m], val[n]); n = m; } } void down(){ int n = 0, m; for(;;){ m=2n+1; if(m>=size) break; if(m+1 val[m+1]) m++; if(val[m] >= val[n]) break; swap(val[m], val[n]); n = m; } } T top(){ return val[0]; } T pop(){ T res = val[0]; size--; if(size > 0) val[0] = val[size], down(); return res; } T push(const T x){ val[size++] = x; up(); return x; } }; ------------------------------- Heap_max ------ template struct Heap_max { int size; T *val; void malloc(const int N){ val = (T*) std::malloc(N*sizeof(T)); size = 0; } void walloc(const int N, void **mem = &wmem){ walloc1d(&val, N, mem); size = 0; } void free(){ std::free(val); } void init(){ size = 0; } void up(){ int n = size - 1, m; while(n){ m = (n-1) / 2; if(val[m] >= val[n]) break; swap(val[m], val[n]); n = m; } } void down(){ int n = 0, m; for(;;){ m=2n+1; if(m>=size) break; if(m+1 0) val[0] = val[size], down(); return res; } T push(const T x){ val[size++] = x; up(); return x; } }; ------------------------------- LHeap ------ template struct LHeap { int *hp, *place, size; T *val; void malloc(int N){ hp = (int*)std::malloc(N*sizeof(int)); place=(int*)std::malloc(N*sizeof(int)); val=(T*)std::malloc(N*sizeof(T)); } void malloc(int N, int ini){ hp = (int*)std::malloc(N*sizeof(int)); place=(int*)std::malloc(N*sizeof(int)); val=(T*)std::malloc(N*sizeof(T)); if(ini) init(N); } void walloc(int N, void **mem=&wmem){ walloc1d(&hp, N, mem); walloc1d(&place, N, mem); walloc1d(&val, N, mem); } void walloc(int N, int ini, void **mem=&wmem){ walloc1d(&hp, N, mem); walloc1d(&place, N, mem); walloc1d(&val, N, mem); if(ini) init(N); } void free(){ std::free(hp); std::free(place); std::free(val); } void init(int N){ int i; size=0; rep(i,N) place[i]=-1; } void up(int n){ int m; while(n){ m=(n-1)/2; if(val[hp[m]]<=val[hp[n]])break; swap(hp[m],hp[n]); swap(place[hp[m]],place[hp[n]]); n=m; } } void down(int n){ int m; for(;;){ m=2*n+1; if(m>=size)break; if(m+1val[hp[m+1]])m++; if(val[hp[m]]>=val[hp[n]])break; swap(hp[m],hp[n]); swap(place[hp[m]],place[hp[n]]); n=m; } } void change(int n, T v){ T f = val[n]; val[n] = v; if(place[n]==-1){ place[n] = size; hp[size++] = n; up(place[n]); } else { if(f < v) down(place[n]); else if(f > v) up(place[n]); } } int pop(void){ int res = hp[0]; place[res] = -1; size--; if(size){ hp[0]=hp[size]; place[hp[0]]=0; down(0); } return res; } }; ------------------------------- DijkstraHeap ------ template struct DijkstraHeap { int *hp, *place, size; char *visited; T *val; void malloc(int N){ hp = (int*)std::malloc(N*sizeof(int)); place = (int*)std::malloc(N*sizeof(int)); visited = (char*)std::malloc(N*sizeof(char)); val = (T*)std::malloc(N*sizeof(T)); } void free(){ std::free(hp); std::free(place); std::free(visited); std::free(val); } void walloc(int N, void **mem=&wmem){ walloc1d(&hp, N, mem); walloc1d(&place, N, mem); walloc1d(&visited, N, mem); walloc1d(&val, N, mem); } void malloc(int N, int init_fg){ malloc(N); if(init_fg) init(N); } void walloc(int N, int init_fg, void **mem=&wmem){ walloc(N,mem); if(init_fg) init(N); } void init(int N){ int i; size = 0; rep(i,N) place[i]=-1; rep(i,N) visited[i]=0; } void up(int n){ int m; while(n){ m=(n-1)/2; if(val[hp[m]]<=val[hp[n]])break; swap(hp[m],hp[n]); swap(place[hp[m]],place[hp[n]]); n=m; } } void down(int n){ int m; for(;;){ m=2*n+1; if(m>=size)break; if(m+1val[hp[m+1]])m++; if(val[hp[m]]>=val[hp[n]]) break; swap(hp[m],hp[n]); swap(place[hp[m]],place[hp[n]]); n=m; } } void change(int n, T v){ if(visited[n]||(place[n]>=0&&val[n]<=v))return; val[n]=v; if(place[n]==-1)place[n]=size,hp[size++]=n,up(place[n]); else up(place[n]); } int pop(void){ int res=hp[0]; place[res]=-1; size--; if(size)hp[0]=hp[size],place[hp[0]]=0,down(0); visited[res]=1; return res; } }; ------------------------------- fenwick_header ------ template struct fenwick{ int size, memory; T *data; void malloc(int mem); void malloc(int mem, int fg); void walloc(int mem, void **workMemory = &wmem); void walloc(int mem, int fg, void **workMemory = &wmem); void free(void); void init(int N); void add(int k, T val); T get(int k); T range(int a, int b); int kth(T k); }; ------------------------------- fenwick ------ template void fenwick::malloc(int mem){ memory = mem; data = (T*)std::malloc(sizeof(T)*mem); } template void fenwick::malloc(int mem, int fg){ memory = mem; data = (T*)std::malloc(sizeof(T)*mem); if(fg) init(mem); } template void fenwick::walloc(int mem, void **workMemory /* = &wmem*/){ memory = mem; walloc1d(&data, mem, workMemory); } template void fenwick::walloc(int mem, int fg, void **workMemory /* = &wmem*/){ memory = mem; walloc1d(&data, mem, workMemory); if(fg) init(mem); } template void fenwick::free(void){ memory = 0; free(data); } template void fenwick::init(int N){ size = N; memset(data,0,sizeof(T)*N); } template void fenwick::add(int k, T val){ while(k < size) data[k] += val, k |= k+1; } template T fenwick::get(int k){ T res = 0; while(k>=0) res += data[k], k = (k&(k+1))-1; return res; } template T fenwick::range(int a, int b){ if(a < 0) a = 0; if(b >= size) b = size - 1; if(b < a) return 0; return get(b) - get(a-1); } template int fenwick::kth(T k){ int i=0, j=size, c; T v; while(i struct fenwick_xor{ int size, memory; T *data; void malloc(int mem); void malloc(int mem, int fg); void walloc(int mem, void **workMemory = &wmem); void walloc(int mem, int fg, void **workMemory = &wmem); void free(void); void init(int N); void add(int k, T val); T get(int k); T range(int a, int b); }; ------------------------------- fenwick_xor ------ template void fenwick_xor::malloc(int mem){ memory = mem; data = (T*)std::malloc(sizeof(T)*mem); } template void fenwick_xor::malloc(int mem, int fg){ memory = mem; data = (T*)std::malloc(sizeof(T)*mem); if(fg) init(mem); } template void fenwick_xor::walloc(int mem, void **workMemory /* = &wmem*/){ memory = mem; walloc1d(&data, mem, workMemory); } template void fenwick_xor::walloc(int mem, int fg, void **workMemory /* = &wmem*/){ memory = mem; walloc1d(&data, mem, workMemory); if(fg) init(mem); } template void fenwick_xor::free(void){ memory = 0; free(data); } template void fenwick_xor::init(int N){ size = N; memset(data,0,sizeof(T)*N); } template void fenwick_xor::add(int k, T val){ while(k < size) data[k] ^= val, k |= k+1; } template T fenwick_xor::get(int k){ T res = 0; while(k>=0) res ^= data[k], k = (k&(k+1))-1; return res; } template T fenwick_xor::range(int a, int b){ if(a < 0) a = 0; if(b >= size) b = size - 1; if(b < a) return 0; return get(b) ^ get(a-1); } ------------------------------- segtree ------ template struct segtree{ int N, logN; T *sum, *mn; int *mnind; T *fixval; char *fixed; T *addval; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ fixed[a*2] = fixed[a*2+1] = 1; fixval[a*2] = fixval[a*2+1] = fixval[a]; sum[a*2] = sum[a*2+1] = sz * fixval[a]; mn[a*2] = mn[a*2+1] = fixval[a]; mnind[a*2] = st; mnind[a*2+1] = st + sz; } else { sum[a*2] = sum[a*2+1] = sz * fixval[a]; mn[a*2] = mn[a*2+1] = fixval[a]; mnind[a*2] = st; mnind[a*2+1] = st + sz; } fixed[a] = 0; addval[a] = 0; return; } if(addval[a] != 0){ if(sz > 1){ if(fixed[a*2]) fixval[a*2] += addval[a]; else addval[a*2] += addval[a]; if(fixed[a*2+1]) fixval[a*2+1] += addval[a]; else addval[a*2+1] += addval[a]; sum[a*2] += sz * addval[a]; sum[a*2+1] += sz * addval[a]; mn[a*2] += addval[a]; mn[a*2+1] += addval[a]; } else { sum[a*2] += sz * addval[a]; sum[a*2+1] += sz * addval[a]; mn[a*2] += addval[a]; mn[a*2+1] += addval[a]; } addval[a] = 0; return; } } inline void push(int a){ int i, aa = a - N, nd, sz, st; for(i=logN;i;i--){ nd = a>>i; sz = 1<<(i-1); st = 2 * sz * (aa>>i); push_one(nd, sz, st); } } inline void build(int a){ int sz = 1, st = a - N; while(a > 1){ if(a%2) st += sz; a /= 2; sz *= 2; if(fixed[a]){ sum[a] = sz * fixval[a]; mn[a] = fixval[a]; } else { sum[a] = sum[a*2] + sum[a*2+1]; if(mn[a*2] <= mn[a*2+1]){ mn[a] = mn[a*2]; mnind[a] = mnind[a*2]; } else { mn[a] = mn[a*2+1]; mnind[a] = mnind[a*2+1]; } if(addval[a] != 0){ mn[a] += addval[a]; sum[a] += sz * addval[a]; } } } } inline void change(int a, int b, T val){ int sz = 1, aa, bb, st_a = a, st_b = b; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ sum[a] = mn[a] = val; a++; st_a += sz; } if(b%2){ b--; st_b -= sz; sum[b] = mn[b] = val; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ fixed[a]=1, fixval[a]=val; sum[a] = sz * val; mn[a] = val; mnind[a] = st_a; a++; st_a += sz; } if(b%2){ b--; st_b -= sz; fixed[b]=1, fixval[b]=val; sum[b] = sz * val; mn[b] = val; mnind[b] = st_b; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline void add(int a, int b, T val){ int sz = 1, aa, bb; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ sum[a] += val; mn[a] += val; a++; } if(b%2){ b--; sum[b] += val; mn[b] += val; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ if(fixed[a]) fixval[a] += val; else addval[a] += val; sum[a] += sz * val; mn[a] += val; a++; } if(b%2){ b--; if(fixed[b]) fixval[b] += val; else addval[b] += val; sum[b] += sz * val; mn[b] += val; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline pair getMin(int a, int b){ pair res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ res = min(res, make_pair(mn[a], mnind[a])); } else { res = make_pair(mn[a], mnind[a]); fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = min(make_pair(mn[b], mnind[b]), tmp); } else { tmp = make_pair(mn[b], mnind[b]); fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = min(res, tmp); return res; } return res; } inline T getMinVal(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ res = min(res, mn[a]); } else { res = mn[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = min(mn[b], tmp); } else { tmp = mn[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = min(res, tmp); return res; } return res; } inline int getMinInd(int a, int b){ return getMin(a,b).second; } inline T getSum(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ res = res + sum[a]; } else { res = sum[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = sum[b] + tmp; } else { tmp = sum[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = res + tmp; return res; } return res; } }; ------------------------------- segtree_Change_Sum ------ template struct segtree_Change_Sum{ int N, logN; T *sum; T *fixval; char *fixed; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ fixed[a*2] = fixed[a*2+1] = 1; fixval[a*2] = fixval[a*2+1] = fixval[a]; sum[a*2] = sum[a*2+1] = sz * fixval[a]; } else { sum[a*2] = sum[a*2+1] = sz * fixval[a]; } fixed[a] = 0; } } inline void push(int a){ int i, aa = a - N, nd, sz, st; for(i=logN;i;i--){ nd = a>>i; sz = 1<<(i-1); st = 2 * sz * (aa>>i); push_one(nd, sz, st); } } inline void build(int a){ int sz = 1, st = a - N; while(a > 1){ if(a%2) st += sz; a /= 2; sz *= 2; if(fixed[a]){ sum[a] = sz * fixval[a]; } else { sum[a] = sum[a*2] + sum[a*2+1]; } } } inline void change(int a, int b, T val){ int sz = 1, aa, bb, st_a = a, st_b = b; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ sum[a] = val; a++; st_a += sz; } if(b%2){ b--; st_b -= sz; sum[b] = val; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ fixed[a]=1, fixval[a]=val; sum[a] = sz * val; a++; st_a += sz; } if(b%2){ b--; st_b -= sz; fixed[b]=1, fixval[b]=val; sum[b] = sz * val; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline T getSum(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ res = res + sum[a]; } else { res = sum[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = sum[b] + tmp; } else { tmp = sum[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = res + tmp; return res; } return res; } }; ------------------------------- segtree_Point_Minval ------ template struct segtree_Point_Minval{ int N, logN; T *mn; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ a /= 2; mn[a] = min(mn[2a], mn[2a+1]); } } inline void change(int a, T val){ mn[a+N] = val; build(a+N); } inline void add(int a, T val){ mn[a+N] += val; build(a+N); } inline T getMinVal(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = min(res, mn[a]); } else { res = mn[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = min(mn[b], tmp); } else { tmp = mn[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = min(res, tmp); return res; } return res; } }; ------------------------------- segtree_Point_Maxval ------ template struct segtree_Point_Maxval{ int N, logN; T *mx; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ a /= 2; mx[a] = max(mx[2a], mx[2a+1]); } } inline void change(int a, T val){ mx[a+N] = val; build(a+N); } inline void add(int a, T val){ mx[a+N] += val; build(a+N); } inline T getMaxVal(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = max(res, mx[a]); } else { res = mx[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = max(mx[b], tmp); } else { tmp = mx[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = max(res, tmp); return res; } return res; } }; ------------------------------- segtree_Point_Min ------ template struct segtree_Point_Min{ int N, logN; T *mn; int *mnind; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ a /= 2; if(mn[a*2] <= mn[a*2+1]){ mn[a] = mn[a*2]; mnind[a] = mnind[a*2]; } else { mn[a] = mn[a*2+1]; mnind[a] = mnind[a*2+1]; } } } inline void change(int a, T val){ mn[a+N] = val; build(a+N); } inline void add(int a, T val){ mn[a+N] += val; build(a+N); } inline pair getMin(int a, int b){ pair res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = min(res, make_pair(mn[a], mnind[a])); } else { res = make_pair(mn[a], mnind[a]); fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = min(make_pair(mn[b], mnind[b]), tmp); } else { tmp = make_pair(mn[b], mnind[b]); fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = min(res, tmp); return res; } return res; } inline T getMinVal(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = min(res, mn[a]); } else { res = mn[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = min(mn[b], tmp); } else { tmp = mn[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = min(res, tmp); return res; } return res; } inline int getMinInd(int a, int b){ return getMin(a,b).second; } }; ------------------------------- segtree_Point_SumMin ------ template struct segtree_Point_SumMin{ int N, logN; T *sum, *mn; int *mnind; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ a /= 2; sum[a] = sum[a*2] + sum[a*2+1]; if(mn[a*2] <= mn[a*2+1]){ mn[a] = mn[a*2]; mnind[a] = mnind[a*2]; } else { mn[a] = mn[a*2+1]; mnind[a] = mnind[a*2+1]; } } } inline void change(int a, T val){ sum[a+N] = mn[a+N] = val; build(a+N); } inline void add(int a, T val){ sum[a+N] = (mn[a+N] += val); build(a+N); } inline pair getMin(int a, int b){ pair res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = min(res, make_pair(mn[a], mnind[a])); } else { res = make_pair(mn[a], mnind[a]); fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = min(make_pair(mn[b], mnind[b]), tmp); } else { tmp = make_pair(mn[b], mnind[b]); fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = min(res, tmp); return res; } return res; } inline T getMinVal(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = min(res, mn[a]); } else { res = mn[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = min(mn[b], tmp); } else { tmp = mn[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = min(res, tmp); return res; } return res; } inline int getMinInd(int a, int b){ return getMin(a,b).second; } inline T getSum(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = res + sum[a]; } else { res = sum[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = sum[b] + tmp; } else { tmp = sum[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = res + tmp; return res; } return res; } }; ------------------------------- segtree_Point_Prod ------ template struct segtree_Point_Prod{ int N, logN; T *mul; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ a /= 2; mul[a] = mul[a*2] * mul[a*2+1]; } } inline void change(int a, T val){ mul[a+N] = val; build(a+N); } inline void add(int a, T val){ mul[a+N] += val; build(a+N); } inline T getProd(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = res * mul[a]; } else { res = mul[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = mul[b] * tmp; } else { tmp = mul[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = res * tmp; return res; } return res; } }; ------------------------------- segtree_Point_Minval2 ------ template struct segtree_Point_Minval2{ int N, logN; T *mn, *mn2; void malloc(int maxN, int once = 0){ int i; for(i=1;i::max(); for(i=N-1;i;i--){ if(mn[2i] <= mn[2i+1]){ mn[i] = mn[2i]; mn2[i] = min(mn2[2i], mn[2i+1]); } else { mn[i] = mn[2i+1]; mn2[i] = min(mn[2i], mn2[2i+1]); } } } inline void build(int a){ while(a > 1){ a /= 2; if(mn[2a] <= mn[2a+1]){ mn[a] = mn[2a]; mn2[a] = min(mn2[2a], mn[2a+1]); } else { mn[a] = mn[2a+1]; mn2[a] = min(mn[2a], mn2[2a+1]); } } } inline void change(int a, T val){ mn[a+N] = val; build(a+N); } inline void add(int a, T val){ mn[a+N] += val; build(a+N); } inline pair getMinVal2(int a, int b){ T res1, res2; a += N; b += N; res1 = res2 = numeric_limits::max(); while(a < b){ if(a%2){ res2 struct segtree_Point_Or{ int N, logN; T *dat; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ a /= 2; dat[a] = (dat[2a] | dat[2a+1]); } } inline void change(int a, T val){ dat[a+N] = val; build(a+N); } inline void add(int a, T val){ dat[a+N] += val; build(a+N); } inline T getOr(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = (res | dat[a]); } else { res = dat[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = (dat[b] | tmp); } else { tmp = dat[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = (res | tmp); return res; } return res; } }; ------------------------------- segtree_Point_And ------ template struct segtree_Point_And{ int N, logN; T *dat; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ a /= 2; dat[a] = (dat[2a] & dat[2a+1]); } } inline void change(int a, T val){ dat[a+N] = val; build(a+N); } inline void add(int a, T val){ dat[a+N] += val; build(a+N); } inline T getAnd(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = (res & dat[a]); } else { res = dat[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = (dat[b] & tmp); } else { tmp = dat[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = (res & tmp); return res; } return res; } }; ------------------------------- segtree_Point_Xor ------ template struct segtree_Point_Xor{ int N, logN; T *dat; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ a /= 2; dat[a] = (dat[2a] ^ dat[2a+1]); } } inline void change(int a, T val){ dat[a+N] = val; build(a+N); } inline void add(int a, T val){ dat[a+N] += val; build(a+N); } inline T getXor(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = (res ^ dat[a]); } else { res = dat[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = (dat[b] ^ tmp); } else { tmp = dat[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = (res ^ tmp); return res; } return res; } }; ------------------------------- segtree_Add_Minval ------ template struct segtree_Add_Minval{ int N, logN; T *mn; T *addval; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ addval[a*2] += addval[a]; addval[a*2+1] += addval[a]; mn[a*2] += addval[a]; mn[a*2+1] += addval[a]; } else { mn[a*2] += addval[a]; mn[a*2+1] += addval[a]; } addval[a] = 0; return; } } inline void push(int a){ int i, aa = a - N, nd, sz, st; for(i=logN;i;i--){ nd = a>>i; sz = 1<<(i-1); st = 2 * sz * (aa>>i); push_one(nd, sz, st); } } inline void build(int a){ int sz = 1, st = a - N; while(a > 1){ if(a%2) st += sz; a /= 2; sz *= 2; mn[a] = min(mn[a*2], mn[a*2+1]); if(addval[a] != 0) mn[a] += addval[a]; } } inline void add(int a, int b, T val){ int sz = 1, aa, bb; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ mn[a] += val; a++; } if(b%2){ b--; mn[b] += val; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ addval[a] += val; mn[a] += val; a++; } if(b%2){ b--; addval[b] += val; mn[b] += val; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline T getMinVal(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ res = min(res, mn[a]); } else { res = mn[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = min(mn[b], tmp); } else { tmp = mn[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = min(res, tmp); return res; } return res; } }; ------------------------------- segtree_ChangeAdd_Sum ------ template struct segtree_ChangeAdd_Sum{ int N, logN; T *sum; T *fixval; char *fixed; T *addval; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ fixed[a*2] = fixed[a*2+1] = 1; fixval[a*2] = fixval[a*2+1] = fixval[a]; sum[a*2] = sum[a*2+1] = sz * fixval[a]; } else { sum[a*2] = sum[a*2+1] = sz * fixval[a]; } fixed[a] = 0; addval[a] = 0; return; } if(addval[a] != 0){ if(sz > 1){ if(fixed[a*2]) fixval[a*2] += addval[a]; else addval[a*2] += addval[a]; if(fixed[a*2+1]) fixval[a*2+1] += addval[a]; else addval[a*2+1] += addval[a]; sum[a*2] += sz * addval[a]; sum[a*2+1] += sz * addval[a]; } else { sum[a*2] += sz * addval[a]; sum[a*2+1] += sz * addval[a]; } addval[a] = 0; return; } } inline void push(int a){ int i, aa = a - N, nd, sz, st; for(i=logN;i;i--){ nd = a>>i; sz = 1<<(i-1); st = 2 * sz * (aa>>i); push_one(nd, sz, st); } } inline void build(int a){ int sz = 1, st = a - N; while(a > 1){ if(a%2) st += sz; a /= 2; sz *= 2; if(fixed[a]){ sum[a] = sz * fixval[a]; } else { sum[a] = sum[a*2] + sum[a*2+1]; if(addval[a] != 0){ sum[a] += sz * addval[a]; } } } } inline void change(int a, int b, T val){ int sz = 1, aa, bb, st_a = a, st_b = b; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ sum[a] = val; a++; st_a += sz; } if(b%2){ b--; st_b -= sz; sum[b] = val; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ fixed[a]=1, fixval[a]=val; sum[a] = sz * val; a++; st_a += sz; } if(b%2){ b--; st_b -= sz; fixed[b]=1, fixval[b]=val; sum[b] = sz * val; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline void add(int a, int b, T val){ int sz = 1, aa, bb; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ sum[a] += val; a++; } if(b%2){ b--; sum[b] += val; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ if(fixed[a]) fixval[a] += val; else addval[a] += val; sum[a] += sz * val; a++; } if(b%2){ b--; if(fixed[b]) fixval[b] += val; else addval[b] += val; sum[b] += sz * val; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline T getSum(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ res = res + sum[a]; } else { res = sum[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = sum[b] + tmp; } else { tmp = sum[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = res + tmp; return res; } return res; } }; ------------------------------- segtree_ChangeP1add_Sum ------ template struct segtree_ChangeP1add_Sum{ int N, logN; T *sum; T *fixval; char *fixed; T *addval, *p1addval; void malloc(int maxN, int once = 0){ int i; for(i=1;i 1){ fixed[a*2] = fixed[a*2+1] = 1; fixval[a*2] = fixval[a*2+1] = fixval[a]; addval[a*2] = p1addval[a*2] = 0; addval[a*2+1] = p1addval[a*2+1] = 0; sum[a*2] = sum[a*2+1] = sz * fixval[a]; } else { sum[a*2] = sum[a*2+1] = sz * fixval[a]; } fixed[a] = 0; } if(addval[a] != 0 || p1addval[a] != 0){ if(sz > 1){ addval[a*2] += addval[a]; addval[a*2+1] += addval[a] + sz * p1addval[a]; p1addval[a*2] += p1addval[a]; p1addval[a*2+1] += p1addval[a]; } sum[a*2] += sz * addval[a] + (ll) sz * (sz-1) / 2 * p1addval[a]; sum[a*2+1] += sz * (addval[a] + sz * p1addval[a]) + (ll) sz * (sz-1) / 2 * p1addval[a]; addval[a] = p1addval[a] = 0; } } inline void push(int a){ int i, aa = a - N, nd, sz, st; for(i=logN;i;i--){ nd = a>>i; sz = 1<<(i-1); st = 2 * sz * (aa>>i); push_one(nd, sz, st); } } inline void build(int a){ int sz = 1, st = a - N; while(a > 1){ if(a%2) st += sz; a /= 2; sz *= 2; if(fixed[a]){ sum[a] = sz * fixval[a]; } else { sum[a] = sum[a*2] + sum[a*2+1]; } if(addval[a] != 0 || p1addval[a] != 0){ sum[a] += sz * addval[a] + (ll) sz * (sz-1) / 2 * p1addval[a]; } } } inline void change(int a, int b, T val){ int sz = 1, aa, bb, st_a = a, st_b = b; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ sum[a] = val; a++; st_a += sz; } if(b%2){ b--; st_b -= sz; sum[b] = val; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ fixed[a]=1, fixval[a]=val; addval[a] = p1addval[a] = 0; sum[a] = sz * val; a++; st_a += sz; } if(b%2){ b--; st_b -= sz; fixed[b]=1, fixval[b]=val; addval[b] = p1addval[b] = 0; sum[b] = sz * val; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline void add(int a, int b, T val){ int sz = 1, aa, bb; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ sum[a] += val; a++; } if(b%2){ b--; sum[b] += val; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ addval[a] += val; sum[a] += sz * val; a++; } if(b%2){ b--; addval[b] += val; sum[b] += sz * val; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline void p1add(int a, int b, T x1, T x0){ int sz = 1, aa, bb; T xa, xb; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); xa = x0; xb = x1 * (b-a) + x0; if(a%2){ sum[a] += xa; a++; xa += sz * x1; } if(b%2){ b--; xb -= sz * x1; sum[b] += xb; } a /= 2; b /= 2; while(a < b){ sz *= 2; if(a%2){ addval[a] += xa; p1addval[a] += x1; sum[a] += sz * xa + (ll) sz * (sz-1) / 2 * x1; a++; xa += sz * x1; } if(b%2){ b--; xb -= sz * x1; addval[b] += xb; p1addval[b] += x1; sum[b] += sz * xb + (ll) sz * (sz-1) / 2 * x1; } a /= 2; b /= 2; } build(aa); build(bb-1); } inline T getSum(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ res = res + sum[a]; } else { res = sum[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = sum[b] + tmp; } else { tmp = sum[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ res = res + tmp; return res; } return res; } }; ------------------------------- segtree_pg_header ------ template struct segtree_pg{ int N, logN; T *val; void malloc(int maxN, int once = 0); void walloc(int maxN, int once = 0, void **mem = &wmem); void free(void); T& operator[](int i); void setN(int n, int zerofill = 1, int dobuild = 1); void build(void); inline void build(int a); inline void change(int a, T v); inline T get(int a, int b); }; ------------------------------- segtree_pg ------ template void segtree_pg::malloc(int maxN, int once /*= 0*/){ int i; for(i=1;i void segtree_pg::walloc(int maxN, int once /*= 0*/, void **mem /*= &wmem*/){ int i; for(i=1;i void segtree_pg::free(void){ delete [] val; } template T& segtree_pg::operator[](int i){ return val[N+i]; } template void segtree_pg::setN(int n, int zerofill /*= 1*/, int dobuild /*= 1*/){ int i; for(i=1,logN=0;i void segtree_pg::build(void){ for(int i=N-1;i;i--) segtree_pg_func(val[i], val[2i], val[2i+1]); } template inline void segtree_pg::build(int a){ while(a > 1){ a /= 2; segtree_pg_func(val[a], val[2a], val[2a+1]); } } template inline void segtree_pg::change(int a, T v){ val[a+N] = v; build(a+N); } template inline T segtree_pg::get(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ segtree_pg_func(res, res, val[a]); } else { res = val[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ segtree_pg_func(tmp, val[b], tmp); } else { tmp = val[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ segtree_pg_func(res, res, tmp); return res; } return res; } ------------------------------- segtree_ph_header ------ template struct segtree_ph{ int N, logN; T *val; void malloc(int maxN, int once = 0); void walloc(int maxN, int once = 0, void **mem = &wmem); void free(void); T& operator[](int i); void setN(int n, int zerofill = 1, int dobuild = 1); void build(void); inline void build(int a); inline void change(int a, T v); inline T get(int a, int b); }; ------------------------------- segtree_ph ------ template void segtree_ph::malloc(int maxN, int once /*= 0*/){ int i; for(i=1;i void segtree_ph::walloc(int maxN, int once /*= 0*/, void **mem /*= &wmem*/){ int i; for(i=1;i void segtree_ph::free(void){ delete [] val; } template T& segtree_ph::operator[](int i){ return val[N+i]; } template void segtree_ph::setN(int n, int zerofill /*= 1*/, int dobuild /*= 1*/){ int i; for(i=1,logN=0;i void segtree_ph::build(void){ for(int i=N-1;i;i--) val[i] = segtree_ph_func(val[2i], val[2i+1]); } template inline void segtree_ph::build(int a){ while(a > 1){ a /= 2; val[a] = segtree_ph_func(val[2a], val[2a+1]); } } template inline void segtree_ph::change(int a, T v){ val[a+N] = v; build(a+N); } template inline T segtree_ph::get(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = segtree_ph_func(res, val[a]); } else { res = val[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = segtree_ph_func(val[b], tmp); } else { tmp = val[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1) return segtree_ph_func(res, tmp); return res; } ------------------------------- segtree_rg_header ------ template struct segtree_rg { int N, logN; SVAL *val; SFUN *fun; void malloc(int maxN, int once = 0); void walloc(int maxN, int once = 0, void **mem = &wmem); void free(void); SVAL& operator[](int i); void setN(int n, int zerofill = 1, int dobuild = 1); void build(void); inline void push_one(int a); inline void push(int a); inline void build(int a); inline void change(int a, int b, SFUN f); inline SVAL get(int a, int b); }; ------------------------------- segtree_rg ------ template void segtree_rg::malloc(int maxN, int once /*= 0*/){ int i; for(i=1;i void segtree_rg::walloc(int maxN, int once /*= 0*/, void **mem /*= &wmem*/){ int i; for(i=1;i void segtree_rg::free(void){ delete [] val; delete [] fun; } template SVAL& segtree_rg::operator[](int i){ return val[N+i]; } template void segtree_rg::setN(int n, int zerofill /*= 1*/, int dobuild /*= 1*/){ int i; for(i=1,logN=0;i void segtree_rg::build(void){ int i; for(i=N-1;i;i--){ segtree_rg_func(val[i], val[2*i], val[2*i+1]); } REP(i,1,N) segtree_rg_id(fun[i]); } template inline void segtree_rg::push_one(int a){ if(2*a < N) segtree_rg_func(fun[2*a], fun[a], fun[2*a]); segtree_rg_func(val[2*a], fun[a], val[2*a]); if(2*a+1 < N) segtree_rg_func(fun[2*a+1], fun[a], fun[2*a+1]); segtree_rg_func(val[2*a+1], fun[a], val[2*a+1]); segtree_rg_id(fun[a]); } template inline void segtree_rg::push(int a){ int i; for(i=logN;i;i--) push_one(a>>i); } template inline void segtree_rg::build(int a){ while(a > 1){ a /= 2; segtree_rg_func(val[a], val[2*a], val[2*a+1]); segtree_rg_func(val[a], fun[a], val[a]); } } template inline void segtree_rg::change(int a, int b, SFUN f){ int aa, bb; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ segtree_rg_func(val[a], f, val[a]); a++; } if(b%2){ b--; segtree_rg_func(val[b], f, val[b]); } a /= 2; b /= 2; while(a < b){ if(a%2){ segtree_rg_func(val[a], f, val[a]); segtree_rg_func(fun[a], f, fun[a]); a++; } if(b%2){ b--; segtree_rg_func(val[b], f, val[b]); segtree_rg_func(fun[b], f, fun[b]); } a /= 2; b /= 2; } build(aa); build(bb-1); } template inline SVAL segtree_rg::get(int a, int b){ SVAL res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ segtree_rg_func(res, res, val[a]); } else { res = val[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ segtree_rg_func(tmp, val[b], tmp); } else { tmp = val[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1){ segtree_rg_func(res, res, tmp); return res; } return res; } ------------------------------- segtree_rh_header ------ template struct segtree_rh { int N, logN, trueN; SVAL *val; SFUN *fun; char *dofun; void malloc(int maxN, int once = 0); void walloc(int maxN, int once = 0, void **mem = &wmem); void free(void); SVAL& operator[](int i); void setN(int n, int zerofill = 1, int dobuild = 1); void build(void); inline void push_one(int a); inline void push(int a); inline void build(int a); inline void change(int a, int b, SFUN f); inline SVAL get(int a, int b); template int max_right(int a, int mx); template int max_right(int a); template int min_left(int b, int mn); template int min_left(int b); }; ------------------------------- segtree_rh ------ template void segtree_rh::malloc(int maxN, int once /*= 0*/){ int i; for(i=1;i void segtree_rh::walloc(int maxN, int once /*= 0*/, void **mem /*= &wmem*/){ int i; for(i=1;i void segtree_rh::free(void){ delete [] val; delete [] fun; } template SVAL& segtree_rh::operator[](int i){ return val[N+i]; } template void segtree_rh::setN(int n, int zerofill /*= 1*/, int dobuild /*= 1*/){ int i; for(i=1,logN=0;i void segtree_rh::build(void){ int i; for(i=N-1;i;i--) val[i] = segtree_rh_merge(val[2*i], val[2*i+1]); REP(i,1,N) dofun[i] = 0; } template inline void segtree_rh::push_one(int a){ if(dofun[a]){ if(2*a < N){ if(dofun[2*a]) fun[2*a] = segtree_rh_compose(fun[a], fun[2*a]); else fun[2*a] = fun[a], dofun[2*a] = 1; } val[2*a] = segtree_rh_apply(fun[a], val[2*a]); if(2*a+1 < N){ if(dofun[2*a+1]) fun[2*a+1] = segtree_rh_compose(fun[a], fun[2*a+1]); else fun[2*a+1] = fun[a], dofun[2*a+1] = 1; } val[2*a+1] = segtree_rh_apply(fun[a], val[2*a+1]); dofun[a] = 0; } } template inline void segtree_rh::push(int a){ int i; for(i=logN;i;i--) push_one(a>>i); } template inline void segtree_rh::build(int a){ while(a > 1){ a /= 2; val[a] = segtree_rh_merge(val[2*a], val[2*a+1]); if(dofun[a]) val[a] = segtree_rh_apply(fun[a], val[a]); } } template inline void segtree_rh::change(int a, int b, SFUN f){ int aa, bb; if(a >= b) return; aa = (a += N); bb = (b += N); push(a); push(b-1); if(a%2){ val[a] = segtree_rh_apply(f, val[a]); a++; } if(b%2){ b--; val[b] = segtree_rh_apply(f, val[b]); } a /= 2; b /= 2; while(a < b){ if(a%2){ val[a] = segtree_rh_apply(f, val[a]); if(dofun[a]) fun[a] = segtree_rh_compose(f, fun[a]); else fun[a] = f, dofun[a] = 1; a++; } if(b%2){ b--; val[b] = segtree_rh_apply(f, val[b]); if(dofun[b]) fun[b] = segtree_rh_compose(f, fun[b]); else fun[b] = f, dofun[b] = 1; } a /= 2; b /= 2; } build(aa); build(bb-1); } template inline SVAL segtree_rh::get(int a, int b){ SVAL res, tmp; int fga = 0, fgb = 0; a += N; b += N; push(a); push(b-1); while(a < b){ if(a%2){ if(fga){ res = segtree_rh_merge(res, val[a]); } else { res = val[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = segtree_rh_merge(val[b], tmp); } else { tmp = val[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1) return segtree_rh_merge(res, tmp); return res; } template template int segtree_rh::max_right(int a, int mx){ int fg = 0; int ta = a, sz = 1; SVAL cur, tmp; if(a>=mx) return mx; a += N; push(a); for(;;){ while(a%2==0) a /= 2, sz *= 2; if(ta + sz <= mx){ if(fg==0){ tmp = val[a]; } else { tmp = segtree_rh_merge(cur, val[a]); } } if(ta + sz > mx || !f(tmp)){ while(a < N){ push_one(a); a *= 2; sz /= 2; if(ta + sz <= mx){ if(fg==0){ tmp = val[a]; } else { tmp = segtree_rh_merge(cur, val[a]); } } if(ta + sz <= mx && f(tmp)){ fg = 1; cur = tmp; a++; ta += sz; } } return a - N; } fg = 1; cur = tmp; if((a & (a+1)) == 0) break; a++; ta += sz; } return mx; } template template int segtree_rh::max_right(int a){ return max_right(a, trueN); } template template int segtree_rh::min_left(int b, int mn){ int fg = 0; int tb = b, sz = 1; SVAL cur, tmp; if(b <= mn) return mn; b += N; push(b-1); for(;;){ while(b%2==0) b /= 2, sz *= 2; if(tb - sz >= mn){ if(fg==0){ tmp = val[b-1]; } else { tmp = segtree_rh_merge(val[b-1], cur); } } if(tb - sz < mn || !f(tmp)){ while(b-1 < N){ push_one(b-1); b *= 2; sz /= 2; if(tb - sz >= mn){ if(fg==0){ tmp = val[b-1]; } else { tmp = segtree_rh_merge(val[b-1], cur); } } if(tb - sz >= mn && f(tmp)){ fg = 1; cur = tmp; b--; tb -= sz; } } return b - N; } fg = 1; cur = tmp; b--; tb -= sz; if(tb <= mn) break; } return mn; } template template int segtree_rh::min_left(int b){ return min_left(b, 0); } ------------------------------- static_segtree_Add_At ------ template struct static_segtree_Add_At{ int N, mem, has_new; T *dat, *ad; void malloc(int maxN, int once = 0){ dat = new T[maxN]; ad = new T[maxN]; if(once) setN(maxN); } void walloc(int maxN, int once = 0, void **mem = &wmem){ walloc1d(&dat, maxN, mem); walloc1d(&ad, maxN, mem); if(once) setN(maxN); } void free(void){ delete [] dat; delete [] ad; } T& operator[](int i){ return dat[i]; } void setN(int n, int zerofill = 1, int dobuild = 1){ N = n; if(zerofill) rep(i,N) dat[i] = 0; if(dobuild) build(); } void build(void){ int i; rep(i,N) ad[i] = 0; has_new = 0; } inline void apply(void){ if(has_new){ int i; T s; s = 0; rep(i,N){ dat[i] += (s += ad[i]); ad[i] = 0; } } has_new = 0; } inline void add(int a, int b, T val){ has_new = 1; ad[a] += val; if(b < N) ad[b] -= val; } inline T getAt(int i){ apply(); return dat[i]; } }; ------------------------------- wAdjEdge1 ------ template void wAdjEdge_L(const int N, const int M, const int *A, const S *B, int **res_sz, S ***res_B, void **mem = &wmem){ int i, j, k; walloc1d(res_sz, N, mem); rep(i,N) (*res_sz)[i] = 0; rep(i,M) (*res_sz)[A[i]]++; walloc1d(res_B, N, mem); rep(i,N) walloc1d(&((*res_B)[i]), (*res_sz)[i], mem); rep(i,N) (*res_sz)[i] = 0; rep(i,M) (*res_B)[A[i]][(*res_sz)[A[i]]++] = B[i]; } ------------------------------- wAdjEdge2 ------ template void wAdjEdge_L(const int N, const int M, const int *A, const S *B, const T *C, int **res_sz, S ***res_B, T ***res_C, void **mem = &wmem){ int i, j, k; walloc1d(res_sz, N, mem); rep(i,N) (*res_sz)[i] = 0; rep(i,M) (*res_sz)[A[i]]++; walloc1d(res_B, N, mem); rep(i,N) walloc1d(&((*res_B)[i]), (*res_sz)[i], mem); walloc1d(res_C, N, mem); rep(i,N) walloc1d(&((*res_C)[i]), (*res_sz)[i], mem); rep(i,N) (*res_sz)[i] = 0; rep(i,M){ (*res_B)[A[i]][(*res_sz)[A[i]]] = B[i]; (*res_C)[A[i]][(*res_sz)[A[i]]] = C[i]; (*res_sz)[A[i]]++; } } ------------------------------- wAdjEdge3 ------ template void wAdjEdge_L(const int N, const int M, const int *A, const S *B, const T *C, const U *D, int **res_sz, S ***res_B, T ***res_C, U ***res_D, void **mem = &wmem){ int i, j, k; walloc1d(res_sz, N, mem); rep(i,N) (*res_sz)[i] = 0; rep(i,M) (*res_sz)[A[i]]++; walloc1d(res_B, N, mem); rep(i,N) walloc1d(&((*res_B)[i]), (*res_sz)[i], mem); walloc1d(res_C, N, mem); rep(i,N) walloc1d(&((*res_C)[i]), (*res_sz)[i], mem); walloc1d(res_D, N, mem); rep(i,N) walloc1d(&((*res_D)[i]), (*res_sz)[i], mem); rep(i,N) (*res_sz)[i] = 0; rep(i,M){ (*res_B)[A[i]][(*res_sz)[A[i]]] = B[i]; (*res_C)[A[i]][(*res_sz)[A[i]]] = C[i]; (*res_D)[A[i]][(*res_sz)[A[i]]] = D[i]; (*res_sz)[A[i]]++; } } ------------------------------- wAdjEdge4 ------ template void wAdjEdge_L(const int N, const int M, int *A, const S *B, const T *C, const U *D, const V *E, int **res_sz, S ***res_B, T ***res_C, U ***res_D, V ***res_E, void **mem = &wmem){ int i, j, k; walloc1d(res_sz, N, mem); rep(i,N) (*res_sz)[i] = 0; rep(i,M) (*res_sz)[A[i]]++; walloc1d(res_B, N, mem); rep(i,M) walloc1d(&((*res_B)[i]), (*res_sz)[i], mem); walloc1d(res_C, N, mem); rep(i,M) walloc1d(&((*res_C)[i]), (*res_sz)[i], mem); walloc1d(res_D, N, mem); rep(i,M) walloc1d(&((*res_D)[i]), (*res_sz)[i], mem); walloc1d(res_E, N, mem); rep(i,M) walloc1d(&((*res_E)[i]), (*res_sz)[i], mem); rep(i,N) (*res_sz)[i] = 0; rep(i,M){ (*res_B)[A[i]][(*res_sz)[A[i]]] = B[i]; (*res_C)[A[i]][(*res_sz)[A[i]]] = C[i]; (*res_D)[A[i]][(*res_sz)[A[i]]] = D[i]; (*res_E)[A[i]][(*res_sz)[A[i]]] = E[i]; (*res_sz)[A[i]]++; } } ------------------------------- graph ------ struct graph{ int N, *es, **edge; ------------------------------- graph_setEdge ------ void setEdge(int N__, int M, int A[], int B[], void **mem = &wmem){ int i; N = N__; walloc1d(&es, N, mem); walloc1d(&edge, N, mem); rep(i,N) es[i] = 0; rep(i,M) es[A[i]]++, es[B[i]]++; rep(i,N) walloc1d(&edge[i], es[i], mem); rep(i,N) es[i] = 0; rep(i,M) edge[A[i]][es[A[i]]++] = B[i], edge[B[i]][es[B[i]]++] = A[i]; } ------------------------------- graph_setDirectEdge ------ void setDirectEdge(int N__, int M, int A[], int B[], void **mem = &wmem){ int i; N = N__; walloc1d(&es, N, mem); walloc1d(&edge, N, mem); walloc1d(&edge[0], M, mem); rep(i,N) es[i] = 0; rep(i,M) es[A[i]]++; rep(i,N) walloc1d(&edge[i], es[i], mem); rep(i,N) es[i] = 0; rep(i,M) edge[A[i]][es[A[i]]++] = B[i]; } ------------------------------- graph_setEdgeRootedTree ------ void setEdgeRootedTree(int N__, int M, int A[], int B[], int root=0, int reorder=0, int cnv[] = NULL, void **mem = &wmem){ int i, j, k; int *dist, *q, qs, qe, *ind; void *tmem; N = N__; tmem = ((char*)(*mem)) + (sizeof(int) * N + 15) + (sizeof(int*) * N + 15) + (sizeof(int) * M + 15 * N); walloc1d(&es, N, mem); walloc1d(&edge, N, mem); rep(i,N) es[i] = 0; rep(i,M) es[A[i]]++, es[B[i]]++; rep(i,N) walloc1d(&edge[i], es[i], &tmem); rep(i,N) es[i] = 0; rep(i,M) edge[A[i]][es[A[i]]++] = B[i], edge[B[i]][es[B[i]]++] = A[i]; walloc1d(&dist, N, &tmem); walloc1d(&q, N, &tmem); walloc1d(&ind, N, &tmem); if(cnv==NULL) walloc1d(&cnv, N, &tmem); rep(i,N) dist[i] = -1; dist[root] = 0; qs = qe = 0; q[qe++] = root; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(dist[k]==-1) dist[k] = dist[i] + 1, q[qe++] = k; } } if(reorder == 0){ rep(i,N) cnv[i] = i; rep(i,N) ind[i] = i; } else { rep(i,N) cnv[i] = q[i]; rep(i,N) ind[cnv[i]] = i; } rep(i,N) es[i] = 0; rep(i,M){ j = A[i]; k = B[i]; if(dist[j] > dist[k]) swap(j, k); es[ind[j]]++; } rep(i,N) walloc1d(&edge[i], es[i], mem); rep(i,N) es[i] = 0; rep(i,M){ j = A[i]; k = B[i]; if(dist[j] > dist[k]) swap(j, k); j = ind[j]; k = ind[k]; edge[j][es[j]++] = k; } } ------------------------------- graph_reverse ------ graph reverse(void **mem = &wmem){ int i, j, k; graph g; g.N = N; walloc1d(&g.es, N, mem); walloc1d(&g.edge, N, mem); rep(i,N) g.es[i] = 0; rep(i,N) rep(j,es[i]) g.es[edge[i][j]]++; rep(i,N) walloc1d(&g.edge[i], g.es[i], mem); rep(i,N) g.es[i] = 0; rep(i,N) rep(j,es[i]){ k = edge[i][j]; g.edge[k][g.es[k]++] = i; } return g; } ------------------------------- graph_reduce ------ graph reduce(int tn, int ind[], int self_e = 0, int dep_e = 0, void **mem = &wmem){ int i, j, k, M = 0; int x, y; graph g; void *tmem; pair *A; rep(i,N) M += es[i]; tmem = ((char*)(*mem)) + sizeof(int**) * N + sizeof(int*) * N + sizeof(int) * M + 16 * (N+2); walloc1d(&A, M, &tmem); M = 0; rep(i,N){ x = ind[i]; if(x < 0) continue; rep(j,es[i]){ y = ind[edge[i][j]]; if(y < 0) continue; if(self_e==0 && x==y) continue; A[M++] = make_pair(x, y); } } if(dep_e==0){ sort(A, A+M); k = 0; rep(i,M){ if(k && A[k-1]==A[i]) continue; A[k++] = A[i]; } M = k; } g.N = tn; walloc1d(&g.es, tn, mem); walloc1d(&g.edge, tn, mem); rep(i,tn) g.es[i] = 0; rep(i,M) g.es[A[i].first]++; rep(i,tn) walloc1d(&g.edge[i], g.es[i], mem); rep(i,tn) g.es[i] = 0; rep(i,M){ j = A[i].first; k = A[i].second; g.edge[j][g.es[j]++] = k; } return g; } ------------------------------- graph_getDist ------ void getDist(int root, int res[], void *mem = wmem){ int i,j,k,*q,s,z; walloc1d(&q, N, &mem); rep(i,N)res[i]=-1; res[root]=0; s=0; z=1; q[0]=root; while(z){ i=q[s++]; z--; rep(j,es[i]){ k=edge[i][j]; if(res[k]>=0)continue; res[k]=res[i]+1; q[s+z++]=k; } } } int getDist(int a, int b, void *mem = wmem){ int i, j, k, *q, s, z, *d; if(a==b) return 0; walloc1d(&d, N, &mem); walloc1d(&q, N, &mem); rep(i,N) d[i] = -1; d[a] = 0; s = 0; z = 1; q[0] = a; while(z){ i = q[s++]; z--; rep(j,es[i]){ k = edge[i][j]; if(d[k] >= 0) continue; d[k] = d[i] + 1; if(k==b) return d[k]; q[s+z++] = k; } } return -1; } ------------------------------- graph_TreeDiameter ------ int TreeDiameter(int &a, int &b, void *mem = wmem){ int i, mx, *d; walloc1d(&d, N, &mem); getDist(0, d, mem); mx = -1; rep(i,N) if(mx < d[i]) mx = d[i], a = i; getDist(a, d, mem); mx = -1; rep(i,N) if(mx < d[i]) mx = d[i], b = i; return mx; } int TreeDiameter(void *mem = wmem){ int a, b; return TreeDiameter(a, b, mem); } ------------------------------- graph_getDistTree_WeightedNode_max ------ template void getDistTree_WeightedNode_max(int root, S1 w[], S2 res[], void *mem = wmem){ int i, j, k, m; int *q, qs = 0, qe = 1; char *vis; walloc1d(&q,N,&mem); walloc1d(&vis,N,&mem); rep(i,N) vis[i] = 0; vis[root] = 1; res[root] = w[root]; q[0] = root; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(vis[k]) continue; res[k] = max(w[k], res[i]); q[qe++] = k; vis[k] = 1; } } } ------------------------------- graph_getDistPairMatrix ------ template void getDistPairMatrix(int k, int ind[], T **d, void *mem = wmem){ int *dist, i, j; walloc1d(&dist, N, &mem); if(k==0) d[0][0] = 0; rep(i,k-1){ getDist(ind[i], dist, mem); rep(j,i,k) d[i][j] = d[j][i] = dist[ind[j]]; } } ------------------------------- graph_SubTreeSize ------ void SubTreeSize(int root, int res[], void *mem = wmem){ int i, j, k, m; int *q, qs = 0, qe = 1; walloc1d(&q,N,&mem); rep(i,N) res[i] = -1; res[root] = 0; q[0] = root; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(res[k]==0) continue; res[k] = 0; q[qe++] = k; } } rrep(m,N){ i = q[m]; res[i] = 1; rep(j,es[i]){ k = edge[i][j]; res[i] += res[k]; } } } ------------------------------- graph_SubTreeWeight ------ template void SubTreeWeight(int root, S weight[], S res[], void *mem = wmem){ int i, j, k, m; int *q, qs = 0, qe = 1; walloc1d(&q,N,&mem); rep(i,N) res[i] = -1; res[root] = 0; q[0] = root; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(res[k]==0) continue; res[k] = 0; q[qe++] = k; } } rrep(m,N){ i = q[m]; res[i] = weight[i]; rep(j,es[i]){ k = edge[i][j]; res[i] += res[k]; } } } ------------------------------- graph_cntShortest ------ template void cntShortest(int root, int dist[], S cnt[], void *mem = wmem){ int i,j,k,*q,s,z; walloc1d(&q, N, &mem); rep(i,N)dist[i]=-1; rep(i,N)cnt[i]=0; dist[root]=0; cnt[root]=1; s=0; z=1; q[0]=root; while(z){ i=q[s++]; z--; rep(j,es[i]){ k=edge[i][j]; if(dist[k]==-1) dist[k] = dist[i] + 1, cnt[k] = 0, q[s+z++] = k; if(dist[k]==dist[i]+1) cnt[k] += cnt[i]; } } } ------------------------------- graph_scc ------ inline int sccDFS(int num[], int st, int mx){ int i,j; num[st]=-2; rep(i,es[st]) { j=edge[st][i]; if(num[j]==-1) mx=sccDFS(num,j,mx); } num[st]=mx; return mx+1; } int scc(int res[], void *mem = wmem){ int i, j, k, ret=0; graph r; int *st, st_size, *num, *nrv; r = reverse(&mem); walloc1d(&st, N, &mem); walloc1d(&num, N, &mem); walloc1d(&nrv, N, &mem); rep(i,N) res[i] = num[i] = -1; k = 0; rep(i,N) if(num[i]==-1) k = sccDFS(num,i,k); rep(i,N) nrv[num[i]] = i; for(k=N-1;k>=0;k--) { i=nrv[k]; if(res[i]>=0)continue; res[i]=ret; st_size=0; st[st_size++]=i; while(st_size){ i=st[--st_size]; rep(j,r.es[i]) if(res[r.edge[i][j]]==-1) res[r.edge[i][j]]=ret, st[st_size++]=r.edge[i][j]; } ret++; } return ret; } ------------------------------- graph_bcc ------ inline void bccDFS(int v, int u, int *res, int *rt, int &rts, int *S, int &Ss, int *inS, int *num, int &tm){ int i, k; num[v] = ++tm; S[Ss++] = v; inS[v] = 1; rt[rts++] = v; rep(i, es[v]){ int w = edge[v][i]; if(!num[w]){ bccDFS(w, v, res, rt, rts, S, Ss, inS, num, tm); } else if(u != w && inS[w]){ while(num[rt[rts-1]] > num[w]) rts--; } } if(v == rt[rts-1]){ k = S[Ss-1]; for(;;){ int w = S[--Ss]; inS[w] = 0; res[w] = k; if(v==w) break; } rts--; } } int bcc(int res[], void *mem=wmem){ int i, k; int *rt, *S, *num, *inS; pair *arr; int rts = 0, Ss = 0, tm = 0; walloc1d(&num, N, &mem); walloc1d(&rt, N, &mem); walloc1d(&S, N, &mem); walloc1d(&inS, N, &mem); memset(num, 0, sizeof(int)*N); memset(inS, 0, sizeof(int)*N); rep(i,N) if(!num[i]) bccDFS(i, N, res, rt, rts, S, Ss, inS, num, tm); arr = (pair*)mem; rep(i,N) arr[i].first = res[i], arr[i].second = i; sort(arr, arr+N); k = 0; rep(i,N){ if(i && arr[i].first != arr[i-1].first) k++; res[arr[i].second] = k; } return k+1; } ------------------------------- graph_articulation ------ void articulationDFS(int n, int b, int &k, int od[], int lw[], int vs[], int &ress, int res[]){ int i, j, a = 0, c = 0; vs[n] = 1; lw[n] = od[n] = k++; rep(i,es[n]){ j = edge[n][i]; if(j==b) continue; if(!vs[j]){ c++; articulationDFS(j, n, k, od, lw, vs, ress, res); lw[n] = 2) a = 1; if(a) res[ress++] = n; } int articulation(int res[], void *mem=wmem){ int i, k = 0, ress = 0; int *od, *lw, *vs; walloc1d(&od, N, &mem); walloc1d(&lw, N, &mem); walloc1d(&vs, N, &mem); rep(i,N) vs[i] = 0; rep(i,N) if(!vs[i]) articulationDFS(i, -1, k, od, lw, vs, ress, res); return ress; } ------------------------------- graph_shortestPath ------ int shortestPath(const int s, const int t, int res[], void *mem=wmem){ int i, j, k; int *q, qs = 0, qe = 0, *b; walloc1d(&b, N, &mem); walloc1d(&q, N, &mem); rep(i,N) b[i] = -1; b[s] = -2; q[qe++] = s; while(qe > qs){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(b[k]!=-1) continue; b[k] = i; q[qe++] = k; } if(b[t]!=-1) break; } if(b[t]==-1) return -1; k = 0; res[k] = i = t; while(i != s) res[++k] = (i = b[i]); std::reverse(res, res+k+1); return k; } ------------------------------- graph_TopologicalSort ------ int TopologicalSort(int res[], void *mem=wmem){ int i, j, k, rs; int *deg, *q, qs = 0, qe = 0; walloc1d(°, N, &mem); walloc1d(&q, N, &mem); rs = 0; rep(i,N) deg[i] = 0; rep(i,N) rep(j,es[i]) deg[edge[i][j]]++; rep(i,N) if(deg[i]==0) q[qe++] = i; while(qs < qe){ i = q[qs++]; res[rs++] = i; rep(j,es[i]){ k = edge[i][j]; deg[k]--; if(deg[k]==0) q[qe++] = k; } } if(rs==N) return 1; return 0; } ------------------------------- graph_longestPath_length ------ int longestPath_length(void *mem = wmem){ int *dp, *arr, res = 0, i, j, ii, jj; walloc1d(&dp, N, &mem); walloc1d(&arr, N, &mem); if(!TopologicalSort(arr, mem)) return -1; rep(i,N) dp[i] = 0; rep(ii,N){ i = arr[ii]; res >?= dp[i]; rep(jj,es[i]){ j = edge[i][jj]; dp[j] >?= dp[i] + 1; } } return res; } ------------------------------- graph_Grundy ------ int Grundy(int res[], void *mem=wmem){ int i, j, k, fg; int *tp, *arr; walloc1d(&tp, N, &mem); fg = TopologicalSort(tp, mem); if(fg==0) return 0; walloc1d(&arr, N, &mem); rep(i,N) arr[i] = -1; rrep[tp](i,N){ rep[edge[i]](j,es[i]) arr[res[j]] = i; for(k=0;;k++) if(arr[k] != i) break; res[i] = k; } return 1; } ------------------------------- graph_preorder ------ int preorder(int res[], int root = 0, void *mem=wmem){ int i, j, k, sts, sz = 0; ll *st; char *vis; walloc1d(&vis, N, &mem); walloc1d(&st, N, &mem); sts = 0; st[sts++] = ((ll)root) << 32; rep(i,N) vis[i] = 0; vis[root] = 1; while(sts){ i = st[--sts] >> 32; j = st[sts] & 2147483647; if(j==0) res[sz++] = i; while(j < es[i]){ k = edge[i][j++]; if(vis[k]) continue; if(j < es[i]) st[sts++] = (((ll)i) << 32) + j; vis[k] = 1; st[sts++] = ((ll)k) << 32; break; } } return sz; } ------------------------------- graph_anUndirectedCycle ------ int anUndirectedCycle(int res[] = NULL, void *mem = wmem){ int i, j, k, m; int *arr, *q, qs, qe, *bk; if(res==NULL) walloc1d(&res, N+1, &mem); rep(i,N) rep(j,es[i]) if(edge[i][j]==i){ res[0] = res[1] = i; return 1; } walloc1d(&arr, N, &mem); walloc1d(&q, N, &mem); walloc1d(&bk, N, &mem); rep(i,N) arr[i] = -1; rep(i,N) rep(j,es[i]){ k = edge[i][j]; if(arr[k] == i){ res[0] = i; res[1] = k; res[2] = i; return 2; } arr[k] = i; } rep(i,N) arr[i] = bk[i] = -1; rep(m,N) if(arr[m]==-1){ qs = qe = 0; q[qe++] = m; arr[m] = 0; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(arr[k]==-1){ arr[k] = arr[i] + 1; bk[k] = i; q[qe++] = k; continue; } if(arr[k] == arr[i] - 1) continue; qs = qe = 1; res[0] = i; q[0] = k; while(i!=k){ if(arr[i] > arr[k]){ res[qs++] = (i = bk[i]); } else { q[qe++] = (k = bk[k]); } } reverse(res, res+qs); rep(i,qe) res[qs++] = q[i]; return qs - 1; } } } return -1; } ------------------------------- graph_shortestCycle ------ int shortestCycle(int res[] = NULL, void *mem=wmem){ int i, j, k, r, sz, tp; int *q, qs, qe, *arr, *bk; if(res==NULL) walloc1d(&res, N+1, &mem); rep(i,N) rep(j,es[i]){ k = edge[i][j]; if(k==i){ res[0] = res[1] = i; return 1; } } walloc1d(&arr, N, &mem); walloc1d(&bk, N, &mem); walloc1d(&q, N, &mem); sz = int_inf; rep(r,N){ rep(i,N) arr[i] = -1; rep(i,N) bk[i] = -1; arr[r] = 0; qs = qe = 0; q[qe++] = r; tp = int_inf; while(qs < qe && tp == int_inf){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(k==r){ bk[k] = i; tp = arr[i] + 1; break; } if(arr[k]==-1){ bk[k] = i; arr[k] = arr[i] + 1; q[qe++] = k; continue; } } } if(sz > tp){ sz = tp; res[tp] = r; k = r; for(;;){ k = bk[k]; res[arr[k]] = k; if(k==r) break; } } } if(sz==int_inf) sz = -1; return sz; } ------------------------------- graph_shortestUndirectedCycle_length ------ int shortestUndirectedCycle_length(void *mem=wmem){ int i, j, k, r, res; int *arr, *q, qs, qe; rep(i,N) rep(j,es[i]) if(edge[i][j]==i) return 1; walloc1d(&arr, N, &mem); rep(i,N) arr[i] = -1; rep(i,N) rep(j,es[i]){ k = edge[i][j]; if(arr[k]==i) return 2; arr[k] = i; } walloc1d(&q, N, &mem); res = int_inf; rep(r,N){ rep(i,N) arr[i] = -1; arr[r] = 0; qs = qe = 0; q[qe++] = r; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(arr[k]==-1){ arr[k] = arr[i] + 1; q[qe++] = k; continue; } if(arr[k]==arr[i]) res = 1){ rep(i,N) deg[i] = es[i]; sort(deg, deg+N); int ss = 0; rep(k,N) ss += es[k]; j = 0; rep(i,N){ j += deg[i]; if(2*j > ss) break; } if(i <= lim) return 0; rep(i,N) if(deg[i] > N-i-1) break; if(i <= lim) return 0; } if(!(skip&2)){ k = 0; uf.walloc(N, &mem); uf.init(N); rep(i,N) rep(j,es[i]) k += uf(i,edge[i][j]); if(k < N-1){ rep(i,N) val[i] = i; rep(i,N) deg[i] = 0; rep(i,N) deg[uf(i)]++; rsortA(N, deg, val); y = N; rrep(x,N) if(deg[x]){ k = 0; rep(i,N){ if(uf(i)!=val[x]) ind[i] = -1, continue; ind[i] = k; rev[k] = i; k++; } y -= k; tmem = mem; g = reduce(k, ind, 1, 1, &mem); m = g.maxIndependenceSet(res+ress, mem, max(-1, lim-(y-2x)-ress), 3); mem = tmem; rep(i,m) res[ress+i] = rev[res[ress+i]]; ress += m; } sort(res,res+ress); return ress; } } k = articulation(ind, mem); rep(i,N) pr[i] = 0; rep(i,k) pr[ind[i]] += (1LL<<40); rep(i,N) rep(j,es[i]) pr[i] += (1LL<<20) - es[edge[i][j]]; x = argmax(pr(N)); k = 0; rep(i,N){ if(i == x) ind[i] = -1, continue; ind[i] = k; rev[k] = i; k++; } tmem = mem; g = reduce(k, ind, 1, 1, &mem); ress = g.maxIndependenceSet(res, mem, lim); mem = tmem; rep(i,ress) res[i] = rev[res[i]]; k = 0; used[x] = 1; rep(j,es[x]) used[edge[x][j]] = 1; rep(i,N){ if(used[i]) ind[i] = -1, continue; ind[i] = k; rev[k] = i; k++; } g = reduce(k, ind, 1, 1, &mem); m = g.maxIndependenceSet(deg, mem, max(ress, lim)-1); if(m+1 > ress){ rep(i,m) res[i] = rev[deg[i]]; res[m++] = x; ress = m; } sort(res,res+ress); return ress; } ------------------------------- graph_countIndependenceSet ------ ll countIndependenceSet(void *mem = wmem, int skip = 0){ int i, j, k, x; ll res; int *deg, *ind; ll *pr; graph g; unionFind uf; void *tmem; if(N == 0) return 1; if(N == 1) return 2; walloc1d(°, N, &mem); walloc1d(&ind, N, &mem); walloc1d(&pr, N, &mem); if(!skip){ k = 0; uf.walloc(N, &mem); uf.init(N); rep(i,N) rep(j,es[i]) k += uf(i,edge[i][j]); if(k < N-1){ res = 1; rep(i,N) deg[i] = 0; rep(i,N) deg[uf(i)]++; rep(x,N) if(deg[x]){ k = 0; rep(i,N){ if(uf(i)!=x) ind[i] = -1, continue; ind[i] = k++; } tmem = mem; g = reduce(k, ind, 1, 1, &mem); res *= g.countIndependenceSet(mem, 1); mem = tmem; } return res; } } k = articulation(ind, mem); rep(i,N) pr[i] = 0; rep(i,k) pr[ind[i]] += (1LL<<40); rep(i,N) rep(j,es[i]) pr[i] += (1LL<<20) - es[edge[i][j]]; x = argmax(pr(N)); res = 0; k = 0; rep(i,N){ if(i == x) ind[i] = -1, continue; ind[i] = k++; } tmem = mem; g = reduce(k, ind, 1, 1, &mem); res += g.countIndependenceSet(mem); mem = tmem; k = 0; rep(i,N) deg[i] = 0; deg[x] = 1; rep(j,es[x]) deg[edge[x][j]] = 1; rep(i,N){ if(deg[i]) ind[i] = -1, continue; ind[i] = k++; } g = reduce(k, ind, 1, 1, &mem); res += g.countIndependenceSet(mem); return res; } ------------------------------- graph_bipartite ------ int bipartite(int res[] = NULL, void *mem = wmem){ int i, j, k, x; int *st, sts; if(res==NULL) walloc1d(&res, N, &mem); walloc1d(&st, N, &mem); rep(i,N) res[i] = -1; rep(x,N) if(res[x]==-1){ res[x] = 0; sts = 0; st[sts++] = x; while(sts){ i = st[--sts]; rep(j,es[i]){ k = edge[i][j]; if(res[k]==-1){ res[k] = 1 - res[i]; st[sts++] = k; } if(res[i] + res[k] != 1) return 0; } } } return 1; } ------------------------------- graph_Rerooting_head ------ template void Rerooting(V res[], void *mem = wmem); ------------------------------- graph_Rerooting ------ template void graph::Rerooting(V res[], void *mem /*= wmem*/){ int i, j, k, ui, ii; int *upind, *dwind, *vis, *q, qs, qe; V **val, **pleft, **pright, tmp; walloc1d(&upind, N, &mem); walloc1d(&dwind, N, &mem); walloc1d(&vis, N, &mem); walloc1d(&q, N, &mem); walloc1d(&val, N, &mem); rep(i,N) walloc1d(&val[i], es[i], &mem); walloc1d(&pleft, N, &mem); rep(i,N) walloc1d(&pleft[i], es[i]+1, &mem); walloc1d(&pright, N, &mem); rep(i,N) walloc1d(&pright[i], es[i]+1, &mem); upind[0] = -1; rep(i,N) vis[i] = 0; qs = qe = 0; q[qe++] = 0; vis[0] = 1; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(vis[k]){ upind[i] = j; continue; } dwind[k] = j; vis[k] = 1; q[qe++] = k; } } rrep(ii,N){ i = q[ii]; rep(j,es[i]) if(j != upind[i]){ k = edge[i][j]; ui = upind[k]; tmp = RerootingMerge(pleft[k][ui], pright[k][es[k]-1-ui]); tmp = RerootingNode(tmp, k); val[i][j] = RerootingEdge(tmp, i, k); } RerootingId(pleft[i][0]); RerootingId(pright[i][0]); rep(j,es[i]){ if(j == upind[i]) break; pleft[i][j+1] = RerootingMerge(pleft[i][j], val[i][j]); } rep(j,es[i]){ if(es[i]-1-j == upind[i]) break; pright[i][j+1] = RerootingMerge(pright[i][j], val[i][es[i]-1-j]); } } rep(ii,N){ i = q[ii]; j = upind[i]; if(j != -1){ k = edge[i][j]; ui = dwind[i]; tmp = RerootingMerge(pleft[k][ui], pright[k][es[k]-1-ui]); tmp = RerootingNode(tmp, k); val[i][j] = RerootingEdge(tmp, i, k); rep(j,upind[i],es[i]){ pleft[i][j+1] = RerootingMerge(pleft[i][j], val[i][j]); } rep(j,es[i]-upind[i]-1,es[i]){ pright[i][j+1] = RerootingMerge(pright[i][j], val[i][es[i]-1-j]); } } res[i] = RerootingNode(pleft[i][es[i]], i); } } ------------------------------- graph_end ------ }; ------------------------------- wgraph ------ template struct wgraph{ int N, *es, **edge; T **cost; graph g; ------------------------------- wgraph_setEdge ------ void setEdge(int N__, int M, int A[], int B[], T C[], void **mem = &wmem){ int i; N = N__; walloc1d(&es, N, mem); rep(i,N) es[i] = 0; rep(i,M) es[A[i]]++, es[B[i]]++; walloc1d(&edge, N, mem); rep(i,N) walloc1d(&edge[i], es[i], mem); walloc1d(&cost, N, mem); rep(i,N) walloc1d(&cost[i], es[i], mem); rep(i,N) es[i] = 0; rep(i,M){ edge[A[i]][es[A[i]]] = B[i]; edge[B[i]][es[B[i]]] = A[i]; cost[A[i]][es[A[i]]++] = C[i]; cost[B[i]][es[B[i]]++] = C[i]; } g.N = N; g.es = es; g.edge = edge; } ------------------------------- wgraph_setDirectEdge ------ void setDirectEdge(int N__, int M, int A[], int B[], T C[], void **mem = &wmem){ int i; N = N__; walloc1d(&es, N, mem); rep(i,N) es[i] = 0; rep(i,M) es[A[i]]++; walloc1d(&edge, N, mem); rep(i,N) walloc1d(&edge[i], es[i], mem); walloc1d(&cost, N, mem); rep(i,N) walloc1d(&cost[i], es[i], mem); rep(i,N) es[i] = 0; rep(i,M){ edge[A[i]][es[A[i]]] = B[i]; cost[A[i]][es[A[i]]++] = C[i]; } g.N = N; g.es = es; g.edge = edge; } ------------------------------- wgraph_setEdgeRootedTree ------ void setEdgeRootedTree(int N__, int M, int A[], int B[], T C[], int root=0, int reorder=0, int cnv[] = NULL, void **mem = &wmem){ int i, j, k; int *dist, *q, qs, qe, *ind; void *tmem; N = N__; tmem = ((char*)(*mem)) + (sizeof(int) * N + 15) + (sizeof(int*) * N + 15) + (sizeof(int) * M + 15 * N) + (sizeof(T*) * N + 15) + (sizeof(T) * M + 15 * N); walloc1d(&es, N, mem); walloc1d(&edge, N, mem); walloc1d(&cost, N, mem); rep(i,N) es[i] = 0; rep(i,M) es[A[i]]++, es[B[i]]++; rep(i,N) walloc1d(&edge[i], es[i], &tmem); rep(i,N) es[i] = 0; rep(i,M) edge[A[i]][es[A[i]]++] = B[i], edge[B[i]][es[B[i]]++] = A[i]; walloc1d(&dist, N, &tmem); walloc1d(&q, N, &tmem); walloc1d(&ind, N, &tmem); if(cnv==NULL) walloc1d(&cnv, N, &tmem); rep(i,N) dist[i] = -1; dist[root] = 0; qs = qe = 0; q[qe++] = root; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(dist[k]==-1) dist[k] = dist[i] + 1, q[qe++] = k; } } if(reorder == 0){ rep(i,N) cnv[i] = i; rep(i,N) ind[i] = i; } else { rep(i,N) cnv[i] = q[i]; rep(i,N) ind[cnv[i]] = i; } rep(i,N) es[i] = 0; rep(i,M){ j = A[i]; k = B[i]; if(dist[j] > dist[k]) swap(j, k); es[ind[j]]++; } rep(i,N) walloc1d(&edge[i], es[i], mem); rep(i,N) walloc1d(&cost[i], es[i], mem); rep(i,N) es[i] = 0; rep(i,M){ j = A[i]; k = B[i]; if(dist[j] > dist[k]) swap(j, k); j = ind[j]; k = ind[k]; edge[j][es[j]] = k; cost[j][es[j]] = C[i]; es[j]++; } } ------------------------------- wgraph_getDist ------ template void getDist(int root, S res[], S unreachable = -1, void *mem = wmem){ int i, j; DijkstraHeap hp; hp.walloc(N, &mem); hp.init(N); hp.change(root,0); while(hp.size){ i = hp.pop(); rep(j,es[i]) hp.change(edge[i][j], hp.val[i]+cost[i][j]); } rep(i,N) res[i] = (hp.visited[i] ? hp.val[i] : unreachable); } ------------------------------- wgraph_getDistT ------ template S getDistT(int a, int b, S unreachable = -1, void *mem = wmem){ int i, j; DijkstraHeap hp; hp.walloc(N, &mem); hp.init(N); hp.change(a,0); while(hp.size){ i = hp.pop(); if(i==b) return hp.val[i]; rep(j,es[i]) hp.change(edge[i][j], hp.val[i]+cost[i][j]); } return unreachable; } ------------------------------- wgraph_getDistDense ------ template void getDistDense(int root, S res[], S unreachable = -1, void *mem = wmem){ int i, j, k; char *vis, *done; walloc1d(&vis, N, &mem); walloc1d(&done, N, &mem); rep(i,N) vis[i] = 0; rep(i,N) done[i] = 0; res[root] = 0; vis[root] = 1; for(;;){ i = -1; rep(j,N) if(!done[j] && vis[j]){ if(i==-1) i = j, continue; if(res[i] > res[j]) i = j; } if(i==-1) break; done[i] = 1; rep(j,es[i]){ k = edge[i][j]; if(vis[k]==0 || res[k] > res[i] + cost[i][j]){ vis[k] = 1; res[k] = res[i] + cost[i][j]; } } } rep(i,N) if(!vis[i]) res[i] = unreachable; } ------------------------------- wgraph_getDistForest ------ template void getDistForest(int root, S res[], S unreachable = -1, void *mem = wmem){ int i,j,k,*q,s,z; char *r; walloc1d(&q,N,&mem); walloc1d(&r,N,&mem); rep(i,N)r[i]=0; res[root]=0; r[root]=1; s=0; z=1; q[0]=root; while(z){ i=q[s++]; z--; rep(j,es[i]){ k=edge[i][j]; if(r[k])continue; res[k]=res[i]+cost[i][j]; r[k]=1; q[s+z++]=k; } } rep(i,N)if(!r[i])res[i]=unreachable; } ------------------------------- wgraph_BellmanFord ------ template void BellmanFord(int root, S res[], S unreachable = -1, S minusInf = -2, int step = -1, void *mem = wmem){ int i, j, k, t; int *inf, *q, qs, qe; S *arr; walloc1d(&q, N, &mem); walloc1d(&inf, N, &mem); walloc1d(&arr, N, &mem); rep(i,N) inf[i] = 0; rep(i,N) res[i] = arr[i] = std::numeric_limits::max(); res[root] = arr[root] = 0; t = step; if(t==-1) t = N; rep(t){ rep(i,N) if(res[i] != std::numeric_limits::max()) rep(j,es[i]){ arr[edge[i][j]] ::max()) res[i] = unreachable; return; } rep(i,N) if(res[i] != std::numeric_limits::max()) rep(j,es[i]){ k = edge[i][j]; if(arr[k] > res[i] + cost[i][j]) inf[k] = 1; } qs = qe = 0; rep(i,N) if(inf[i]) q[qe++] = i; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(inf[k]==0){ inf[k] = 1; q[qe++] = k; } } } rep(i,N) if(res[i]==std::numeric_limits::max()) res[i] = unreachable; rep(i,N) if(inf[i]==1) res[i] = minusInf; } ------------------------------- wgraph_getDist01 ------ template void getDist01(int root, S res[], void *mem = wmem){ int i, j, k, nd; int *q, qs, qe; char *don; walloc1d(&q, 2*N, &mem); walloc1d(&don, N, &mem); rep(i,N) res[i] = -1; rep(i,N) don[i] = 0; qs = qe = N; q[qe++] = root; res[root] = 0; while(qs < qe){ i = q[qs++]; if(don[i]) continue; don[i] = 1; rep(j,es[i]){ k = edge[i][j]; nd = res[i] + cost[i][j]; if(res[k]==-1 || res[k] > nd){ res[k] = nd; if(cost[i][j]==0){ q[--qs] = k; } else { q[qe++] = k; } } } } } int getDist01(int a, int b, void *mem = wmem){ int i, j, k, nd; int *res, *q, qs, qe; char *don; walloc1d(&res, N, &mem); walloc1d(&q, 2*N, &mem); walloc1d(&don, N, &mem); rep(i,N) res[i] = -1; rep(i,N) don[i] = 0; qs = qe = N; q[qe++] = a; res[a] = 0; while(qs < qe){ i = q[qs++]; if(i==b) return res[b]; if(don[i]) continue; don[i] = 1; rep(j,es[i]){ k = edge[i][j]; nd = res[i] + cost[i][j]; if(res[k]==-1 || res[k] > nd){ res[k] = nd; if(cost[i][j]==0){ q[--qs] = k; } else { q[qe++] = k; } } } } return -1; } ------------------------------- wgraph_MST_Prim_cost ------ T MST_Prim_cost(void *mem = wmem){ int i, j; T res = 0; DijkstraHeap hp; hp.walloc(N, &mem); hp.init(N); hp.change(0,0); while(hp.size){ i = hp.pop(); res += hp.val[i]; rep(j,es[i]) hp.change(edge[i][j], cost[i][j]); } return res; } int MST_Prim_cost(T &res, void *mem = wmem){ int i, j, cnt = 0; res = 0; DijkstraHeap hp; hp.walloc(N, &mem); hp.init(N); hp.change(0,0); while(hp.size){ i = hp.pop(); res += hp.val[i]; cnt++; rep(j,es[i]) hp.change(edge[i][j], cost[i][j]); } if(cnt==N) return 1; return 0; } ------------------------------- wgraph_Rerooting_head ------ template void Rerooting(V res[], void *mem = wmem); ------------------------------- wgraph_Rerooting ------ template template void wgraph::Rerooting(V res[], void *mem /*= wmem*/){ int i, j, k, ui, ii; int *upind, *dwind, *vis, *q, qs, qe; V **val, **pleft, **pright, tmp; walloc1d(&upind, N, &mem); walloc1d(&dwind, N, &mem); walloc1d(&vis, N, &mem); walloc1d(&q, N, &mem); walloc1d(&val, N, &mem); rep(i,N) walloc1d(&val[i], es[i], &mem); walloc1d(&pleft, N, &mem); rep(i,N) walloc1d(&pleft[i], es[i]+1, &mem); walloc1d(&pright, N, &mem); rep(i,N) walloc1d(&pright[i], es[i]+1, &mem); upind[0] = -1; rep(i,N) vis[i] = 0; qs = qe = 0; q[qe++] = 0; vis[0] = 1; while(qs < qe){ i = q[qs++]; rep(j,es[i]){ k = edge[i][j]; if(vis[k]){ upind[i] = j; continue; } dwind[k] = j; vis[k] = 1; q[qe++] = k; } } rrep(ii,N){ i = q[ii]; rep(j,es[i]) if(j != upind[i]){ k = edge[i][j]; ui = upind[k]; tmp = wRerootingMerge(pleft[k][ui], pright[k][es[k]-1-ui]); tmp = wRerootingNode(tmp, k); val[i][j] = wRerootingEdge(tmp, cost[i][j], i, k); } wRerootingId(pleft[i][0]); wRerootingId(pright[i][0]); rep(j,es[i]){ if(j == upind[i]) break; pleft[i][j+1] = wRerootingMerge(pleft[i][j], val[i][j]); } rep(j,es[i]){ if(es[i]-1-j == upind[i]) break; pright[i][j+1] = wRerootingMerge(pright[i][j], val[i][es[i]-1-j]); } } rep(ii,N){ i = q[ii]; j = upind[i]; if(j != -1){ k = edge[i][j]; ui = dwind[i]; tmp = wRerootingMerge(pleft[k][ui], pright[k][es[k]-1-ui]); tmp = wRerootingNode(tmp, k); val[i][j] = wRerootingEdge(tmp, cost[i][j], i, k); rep(j,upind[i],es[i]){ pleft[i][j+1] = wRerootingMerge(pleft[i][j], val[i][j]); } rep(j,es[i]-upind[i]-1,es[i]){ pright[i][j+1] = wRerootingMerge(pright[i][j], val[i][es[i]-1-j]); } } res[i] = wRerootingNode(pleft[i][es[i]], i); } } ------------------------------- wgraph_end ------ }; ------------------------------- HLD ------ struct HLD{ int N; int *es, **edge; int *group, *groupind; int groupNum, *groupSize, **groupNode, *groupUpNode, *groupDepth; void init(graph g, void **mem = &wmem){ init(g.N, g.es, g.edge, mem); } void init(int N__, int *es__, int **edge__, void **mem = &wmem){ int i, j, k, x, y, mx; int *q, q_st, q_ed, *sz; char *vis; void *tmpmem; N = N__; es = es__; edge = edge__; walloc1d(&group, N, mem); walloc1d(&groupind, N, mem); tmpmem = *mem; walloc1d(&q, N, &tmpmem); walloc1d(&sz, N, &tmpmem); walloc1d(&vis, N, &tmpmem); rep(i,N) vis[i] = 0; q_st = 0; q_ed = 1; q[0] = 0; vis[0] = 1; while(q_st < q_ed){ i = q[q_st++]; rep(j,es[i]){ k = edge[i][j]; if(!vis[k]) vis[k] = 1, q[q_ed++] = k; } } rep(i,N) sz[i] = 0; for(j=N-1;j>=0;j--){ i = q[j]; sz[i] = 1; rep(k,es[i]) sz[i] += sz[edge[i][k]]; } rep(i,N) group[i] = -1; groupNum = 0; rep(j,N){ i = q[j]; if(group[i]>=0) continue; group[i] = groupNum++; groupind[i] = 0; for(;;){ mx = -1; rep(k,es[i]){ if(group[edge[i][k]] != -1) continue; if(mx==-1) mx = k; else if(sz[edge[i][k]] > sz[edge[i][mx]]) mx = k; } if(mx==-1) break; group[edge[i][mx]] = group[i]; groupind[edge[i][mx]] = groupind[i]+1; i = edge[i][mx]; } } walloc1d(&groupSize, groupNum, mem); walloc1d(&groupUpNode, groupNum, mem); walloc1d(&groupDepth, groupNum, mem); rep(i,groupNum) groupSize[i] = 0; rep(i,N) groupSize[group[i]]++; walloc1d(&groupNode, groupNum, mem); rep(i,groupNum) walloc1d(&groupNode[i], groupSize[i], mem); rep(i,N) groupNode[group[i]][groupind[i]] = i; rep(i,groupNum) groupDepth[i] = -1; groupUpNode[0] = -1; groupDepth[0] = 0; rep(x,groupNum) rep(y,groupSize[x]){ i = groupNode[x][y]; rep(j,es[i]){ k = edge[i][j]; if(x != group[k] && groupDepth[group[k]]==-1){ groupUpNode[group[k]] = i; groupDepth[group[k]] = groupDepth[x] + 1; } } } } int lca(int x, int y){ int x1, y1, x2, y2; x1 = group[x]; x2 = groupind[x]; y1 = group[y]; y2 = groupind[y]; while(groupDepth[x1] > groupDepth[y1]){ x = groupUpNode[x1]; x1 = group[x]; x2 = groupind[x]; } while(groupDepth[x1] < groupDepth[y1]){ y = groupUpNode[y1]; y1 = group[y]; y2 = groupind[y]; } while(x1 != y1){ x = groupUpNode[x1]; x1 = group[x]; x2 = groupind[x]; y = groupUpNode[y1]; y1 = group[y]; y2 = groupind[y]; } if(x2 <= y2) return x; return y; } int depth(int x){ int x1, x2, res = 0; x1 = group[x]; x2 = groupind[x]; while(groupUpNode[x1] != -1){ res += x2 + 1; x = groupUpNode[x1]; x1 = group[x]; x2 = groupind[x]; } return res + x2; } int dist(int x, int y){ int x1, y1, x2, y2, res = 0; x1 = group[x]; x2 = groupind[x]; y1 = group[y]; y2 = groupind[y]; while(groupDepth[x1] > groupDepth[y1]){ res += x2 + 1; x = groupUpNode[x1]; x1 = group[x]; x2 = groupind[x]; } while(groupDepth[x1] < groupDepth[y1]){ res += y2 + 1; y = groupUpNode[y1]; y1 = group[y]; y2 = groupind[y]; } while(x1 != y1){ res += x2 + y2 + 2; x = groupUpNode[x1]; x1 = group[x]; x2 = groupind[x]; y = groupUpNode[y1]; y1 = group[y]; y2 = groupind[y]; } if(x2 <= y2) return res + y2 - x2; return res + x2 - y2; } int up(int x){ int x1 = group[x]; int x2 = groupind[x]; if(x2==0) return groupUpNode[x1]; return groupNode[x1][x2-1]; } int up(int x, int d){ int x1 = group[x]; int x2 = groupind[x]; while(d > x2){ if(groupUpNode[x1]==-1) return -1; d -= x2 + 1; x = groupUpNode[x1]; x1 = group[x]; x2 = groupind[x]; } return groupNode[x1][x2-d]; } }; ------------------------------- HLD_fenwick ------ template struct HLD_fenwick{ HLD *hld; fenwick *fen; void init(HLD *hld__, void **mem = &wmem){ int i, j; hld = hld__; walloc1d(&fen, hld->groupNum, mem); rep(i,hld->groupNum){ fen[i].walloc(hld->groupSize[i], mem); fen[i].init(hld->groupSize[i]); } } inline void add(int u, T val){ int ug, ui; ug = hld->group[u]; ui = hld->groupind[u]; fen[ug].add(ui, val); } inline T get(int u, int v){ T res; int ug, vg, ui, vi; ug = hld->group[u]; vg = hld->group[v]; res = 0; while(ug != vg){ if(hld->groupDepth[ug] < hld->groupDepth[vg]){ swap(u, v); swap(ug, vg); } res += fen[ug].get(hld->groupind[u]); u = hld->groupUpNode[ug]; ug = hld->group[u]; } ui = hld->groupind[u]; vi = hld->groupind[v]; res += fen[ug].range(min(ui,vi), max(ui,vi)); return res; } }; ------------------------------- HLD_segtree ------ template struct HLD_segtree{ HLD *hld; segtree *seg; void init(HLD *hld__, T initval[], void **mem = &wmem){ int i, j; hld = hld__; walloc1d(&seg, hld->groupNum, mem); rep(i,hld->groupNum){ seg[i].walloc(hld->groupSize[i], 0, mem); seg[i].setN(hld->groupSize[i], 0, 0); if(initval!=NULL) rep(j,hld->groupSize[i]) seg[i][j] = initval[ hld->groupNode[i][j] ]; else rep(j,hld->groupSize[i]) seg[i][j] = 0; seg[i].build(); } } inline void change(int u, int v, T val){ int ug, vg, ui, vi; ug = hld->group[u]; vg = hld->group[v]; while(ug != vg){ if(hld->groupDepth[ug] < hld->groupDepth[vg]){ swap(u, v); swap(ug, vg); } seg[ug].change(0, hld->groupind[u]+1, val); u = hld->groupUpNode[ug]; ug = hld->group[u]; } ui = hld->groupind[u]; vi = hld->groupind[v]; seg[ug].change(min(ui,vi), max(ui,vi)+1, val); } inline void add(int u, int v, T val){ int ug, vg, ui, vi; ug = hld->group[u]; vg = hld->group[v]; while(ug != vg){ if(hld->groupDepth[ug] < hld->groupDepth[vg]){ swap(u, v); swap(ug, vg); } seg[ug].add(0, hld->groupind[u]+1, val); u = hld->groupUpNode[ug]; ug = hld->group[u]; } ui = hld->groupind[u]; vi = hld->groupind[v]; seg[ug].add(min(ui,vi), max(ui,vi)+1, val); } inline pair getMin(int u, int v){ pair res, tmp; int ug, vg, ui, vi; ug = hld->group[u]; vg = hld->group[v]; res.first = numeric_limits::max(); res.second = -1; while(ug != vg){ if(hld->groupDepth[ug] < hld->groupDepth[vg]){ swap(u, v); swap(ug, vg); } tmp = seg[ug].getMin(0, hld->groupind[u]+1); tmp.second = hld->groupNode[ug][tmp.second]; res groupUpNode[ug]; ug = hld->group[u]; } ui = hld->groupind[u]; vi = hld->groupind[v]; tmp = seg[ug].getMin(min(ui,vi), max(ui,vi)+1); tmp.second = hld->groupNode[ug][tmp.second]; res group[u]; vg = hld->group[v]; res = 0; while(ug != vg){ if(hld->groupDepth[ug] < hld->groupDepth[vg]){ swap(u, v); swap(ug, vg); } res += seg[ug].getSum(0, hld->groupind[u]+1); u = hld->groupUpNode[ug]; ug = hld->group[u]; } ui = hld->groupind[u]; vi = hld->groupind[v]; res += seg[ug].getSum(min(ui,vi), max(ui,vi)+1); return res; } inline void change_edge(int u, int v, T val){ int x, z, d; z = hld->lca(u, v); d = hld->depth(z); if(z != u){ x = hld->up(u, hld->depth(u) - d - 1); change(u, x, val); } if(z != v){ x = hld->up(v, hld->depth(v) - d - 1); change(v, x, val); } } inline void add_edge(int u, int v, T val){ int x, z, d; z = hld->lca(u, v); d = hld->depth(z); if(z != u){ x = hld->up(u, hld->depth(u) - d - 1); add(u, x, val); } if(z != v){ x = hld->up(v, hld->depth(v) - d - 1); add(v, x, val); } } inline pair getMin_edge(int u, int v){ int x, z, d; pair res, tmp; res.first = numeric_limits::max(); res.second = -1; z = hld->lca(u, v); d = hld->depth(z); if(z != u){ x = hld->up(u, hld->depth(u) - d - 1); tmp = getMin(u, x); res up(v, hld->depth(v) - d - 1); tmp = getMin(v, x); res lca(u, v); d = hld->depth(z); if(z != u){ x = hld->up(u, hld->depth(u) - d - 1); res += getSum(u, x); } if(z != v){ x = hld->up(v, hld->depth(v) - d - 1); res += getSum(v, x); } return res; } }; ------------------------------- maxflow ------ template struct maxflow{ int node, st, ed; int *es, *emem, **edge, **rev, *level, *qq; T **flow, eps; void malloc(int N){ int i; es = (int*)std::malloc(N*sizeof(int)); emem = (int*)std::malloc(N*sizeof(int)); level = (int*)std::malloc(N*sizeof(int)); qq = (int*)std::malloc(N*sizeof(int)); edge = (int**)std::malloc(N*sizeof(int*)); rev = (int**)std::malloc(N*sizeof(int*)); flow = (T**)std::malloc(N*sizeof(T*)); rep(i,N) emem[i] = 0, edge[i] = rev[i] = NULL, flow[i] = NULL; } void malloc(int N, int init_flag){ int i; es = (int*)std::malloc(N*sizeof(int)); emem = (int*)std::malloc(N*sizeof(int)); level = (int*)std::malloc(N*sizeof(int)); qq = (int*)std::malloc(N*sizeof(int)); edge = (int**)std::malloc(N*sizeof(int*)); rev = (int**)std::malloc(N*sizeof(int*)); flow = (T**)std::malloc(N*sizeof(T*)); rep(i,N) emem[i] = 0, edge[i] = rev[i] = NULL, flow[i] = NULL; if(init_flag) init(N); } void walloc(int N, void**mem = &wmem){ int i; walloc1d(&es, N, mem); walloc1d(&emem, N, mem); walloc1d(&level, N, mem); walloc1d(&qq, N, mem); walloc1d(&edge, N, mem); walloc1d(&rev, N, mem); walloc1d(&flow, N, mem); (*mem) = (flow + N); } void walloc(int N, int init_flag, void**mem = &wmem){ int i; walloc1d(&es, N, mem); walloc1d(&emem, N, mem); walloc1d(&level, N, mem); walloc1d(&qq, N, mem); walloc1d(&edge, N, mem); walloc1d(&rev, N, mem); walloc1d(&flow, N, mem); (*mem) = (flow + N); if(init_flag) init(N); } void levelize(void){ int i, j, k, t; int q_st = 0, q_ed = 1; rep(i,node) level[i] = -1; level[st] = 0; qq[0] = st; while(q_st != q_ed){ i = qq[q_st++]; t = level[i] + 1; rep(j,es[i]) if(flow[i][j] > eps){ k = edge[i][j]; if(level[k]!=-1) continue; level[k] = t; qq[q_ed++] = k; if(k==ed) return; } } } S pushflow(int i, S lim){ int j, k, ji; S s, t, res = 0; if(i==ed) return lim; rep(j,es[i]) if(flow[i][j] > eps){ k = edge[i][j]; if(level[k] != level[i]+1) continue; s = min(lim, (S)flow[i][j]); t = pushflow(k, s); if(!t) continue; res += t; lim -= t; ji = rev[i][j]; flow[i][j] -= t; flow[k][ji] += t; if(!lim) break; } if(lim) level[i] = -1; return res; } S solve(int st_, int ed_){ S res = 0; st = st_; ed = ed_; for(;;){ levelize(); if(level[ed] == -1) break; res += pushflow(st, numeric_limits::max()); } return res; } void init(int N){ int i; node = N; rep(i,N) es[i] = 0; eps = (T)1e-9; } void memoryExpand(int i, int sz){ if(sz <= emem[i]) return; sz = max(sz, max(3, emem[i]*2)); emem[i]=sz; edge[i] = (int*)realloc(edge[i], sz*sizeof(int)); rev[i] = (int*)realloc(rev[i], sz*sizeof(int)); flow[i] = (T*)realloc(flow[i], sz*sizeof(T)); } void addEdge(int n1, int n2, T f1, T f2 = 0){ int s1 = es[n1]++, s2 = es[n2]++; if(s1 >= emem[n1]) memoryExpand(n1, es[n1]); if(s2 >= emem[n2]) memoryExpand(n2, es[n2]); edge[n1][s1]=n2; edge[n2][s2]=n1; flow[n1][s1]=f1; flow[n2][s2]=f2; rev[n1][s1]=s2; rev[n2][s2]=s1; } void addEdgeAdv(int n1, int n2, T f1, T f2 = 0){ int s1 = es[n1]++, s2 = es[n2]++; edge[n1][s1]=n2; edge[n2][s2]=n1; flow[n1][s1]=f1; flow[n2][s2]=f2; rev[n1][s1]=s2; rev[n2][s2]=s1; } void setGraph(int N, int M, int n1[], int n2[], T f1[], T f2[]){ int i; node = N; rep(i,N) es[i] = 0; rep(i,M) es[n1[i]]++, es[n2[i]]++; rep(i,N) memoryExpand(i, es[i]); rep(i,N) es[i] = 0; rep(i,M) addEdgeAdv(n1[i], n2[i], f1[i], f2[i]); eps = (T)1e-9; } void setGraph_w(int N, int M, int n1[], int n2[], T f1[], T f2[], void **mem = wmem){ int i, j, k; node = N; rep(i,N) es[i] = emem[i] = 0; rep(i,M) es[n1[i]]++, es[n2[i]]++; edge[0] = (int*)(*mem); REP(i,1,N) edge[i] = edge[i-1] + es[i-1]; rev[0] = edge[N-1] + es[N-1]; REP(i,1,N) rev[i] = rev[i-1] + es[i-1]; flow[0] = (T*)(rev[N-1] + es[N-1]); REP(i,1,N) flow[i] = flow[i-1] + es[i-1]; *mem = (void*)(flow[N-1] + es[N-1]); rep(i,N) es[i] = 0; rep(i,M) addEdgeAdv(n1[i], n2[i], f1[i], f2[i]); eps = (T)1e-9; } }; ------------------------------- minCostFlow ------ template struct minCostFlow { int node; int *es, *emem, **edge, **rev; FT **flow, f_eps; CT **cost, *potential, c_eps; LHeap hp; char *reached; FT *cur_flow; CT *cur_cost; int *back_edge; void malloc(int N){ int i; es = (int*)std::malloc(N*sizeof(int)); emem = (int*)std::malloc(N*sizeof(int)); edge = (int**)std::malloc(N*sizeof(int*)); rev = (int**)std::malloc(N*sizeof(int*)); flow = (FT**)std::malloc(N*sizeof(FT*)); cost = (CT**)std::malloc(N*sizeof(CT*)); rep(i,N){ emem[i] = 0; edge[i] = rev[i] = NULL; flow[i] = NULL; cost[i] = NULL; } hp.malloc(N); reached = (char*)std::malloc(N*sizeof(char)); cur_flow = (FT*)std::malloc(N*sizeof(FT)); cur_cost = (CT*)std::malloc(N*sizeof(CT)); potential = (CT*)std::malloc(N*sizeof(CT)); back_edge = (int*)std::malloc(N*sizeof(int)); node = N; rep(i,N) es[i] = 0; f_eps = (FT)1e-9; c_eps = (CT)1e-9; } void init(int N){ int i; node = N; rep(i,N) es[i] = 0; f_eps = (FT)1e-9; c_eps = (CT)1e-9; } void memoryExpand(int i, int sz){ if(sz <= emem[i]) return; sz = max(sz, 3, 2emem[i]); emem[i] = sz; edge[i] = (int*)realloc(edge[i], sz*sizeof(int)); rev[i] = (int*)realloc(rev[i], sz*sizeof(int)); flow[i] = (FT*)realloc(flow[i], sz*sizeof(FT)); cost[i] = (CT*)realloc(cost[i], sz*sizeof(CT)); } void addEdge(int n1, int n2, FT f, CT c){ int s1 = es[n1]++; int s2 = es[n2]++; if(s1 >= emem[n1]) memoryExpand(n1, es[n1]); if(s2 >= emem[n2]) memoryExpand(n2, es[n2]); edge[n1][s1] = n2; edge[n2][s2] = n1; rev[n1][s1] = s2; rev[n2][s2] = s1; flow[n1][s1] = f; flow[n2][s2] = 0; cost[n1][s1] = c; cost[n2][s2] = -c; } template void solve(int st, int ed, FTS &fres, CTS &cres, FT flim = -1, CT clim = 0){ int i, j, k, l; FT f; CT nc; fres = 0; cres = 0; rep(i,node) potential[i] = 0; for(;;){ if(flim >= -f_eps && flim <= f_eps) break; hp.init(node); rep(i,node) reached[i] = 0; reached[st] = 1; cur_cost[st] = 0; l = 0; hp.change(st, cur_cost[st]); while(hp.size){ i = hp.pop(); rep(j, es[i]){ if(flow[i][j] <= f_eps) continue; k = edge[i][j]; nc = cur_cost[i] + cost[i][j] + potential[i] - potential[k]; if(reached[k]==0 || cur_cost[k] > nc+c_eps){ reached[k] = 1; cur_cost[k] = nc; cur_flow[k] = flow[i][j]; if(i != st) cur_flow[k] = clim) break; f = cur_flow[ed]; if(flim >= -f_eps){ f int KMP(T A[], int As, T B[], int Bs, int res[] = NULL, int *fail = (int*)wmem){ int i, k, cnt = 0; k = fail[0] = -1; rep(i,Bs){ while(k>=0 && B[k]!=B[i]) k = fail[k]; fail[i+1] = ++k; } if(res != NULL) rep(i,As) res[i] = 0; k = 0; rep(i,As){ while(k >= 0 && B[k] != A[i]) k = fail[k]; k++; if(k == Bs){ cnt++; if(res != NULL) res[i-Bs+1] = 1; k = fail[k]; } } return cnt; } template int KMP(T A[], int As, T B[], int Bs, S res[], int *fail = (int*)wmem){ int i, k, cnt = 0; k = fail[0] = -1; rep(i,Bs){ while(k>=0 && B[k]!=B[i]) k = fail[k]; fail[i+1] = ++k; } if(res != NULL) rep(i,As) res[i] = 0; k = 0; rep(i,As){ while(k >= 0 && B[k] != A[i]) k = fail[k]; k++; if(k == Bs){ cnt++; if(res != NULL) res[i-Bs+1] = 1; k = fail[k]; } } return cnt; } ------------------------------- isSubsequence ------ template int isSubsequence(int As, const T1 A[], int Bs, const T2 B[]){ int i, j = 0; if(Bs==0) return 1; rep(i,As) if(A[i]==B[j]){ j++; if(j==Bs) break; } return j == Bs; } int isSubsequence(string A, string B){ int i, j = 0; if(B.size()==0) return 1; rep(i,A.size()) if(A[i]==B[j]){ j++; if(j==B.size()) break; } return j == B.size(); } ------------------------------- isSubsequence_r ------ int isSubsequence_r(string &A, string &B){ int i, j = 0; if(B.size()==0) return 1; rep(i,A.size()) if(A[i]==B[j]){ j++; if(j==B.size()) break; } return j == B.size(); } ------------------------------- cntSubsequence ------ template R cntSubsequence(int As, const T A[], int Bs, const T B[], void *mem = wmem){ int i, j, k; int *aa, *bb, sz; int *s, **arr; R *dp; if(Bs > As) return 0; walloc1d(&aa, As, &mem); walloc1d(&bb, Bs, &mem); sz = coordcomp(As, A, Bs, B, aa, bb, mem); walloc1d(&s, sz, &mem); walloc1d(&arr, sz, &mem); rep(i,sz) s[i] = 0; rep(i,Bs) s[bb[i]]++; rep(i,sz) if(s[i]) walloc1d(&arr[i], s[i], &mem); rep(i,sz) s[i] = 0; rrep(i,Bs) arr[bb[i]][s[bb[i]]++] = i; walloc1d(&dp, Bs+1, &mem); dp[0] = 1; rep(i,1,Bs+1) dp[i] = 0; rep(i,As){ k = aa[i]; rep(j,s[k]) dp[arr[k][j]+1] += dp[arr[k][j]]; } return dp[Bs]; } template R cntSubsequence(int As, const T1 A[], int Bs, const T2 B[], void *mem = wmem){ int i; typename cLtraits_common_type::type *aa, *bb; if(Bs > As) return 0; walloc1d(&aa, As, &mem); walloc1d(&bb, Bs, &mem); rep(i,As) aa[i] = A[i]; rep(i,Bs) bb[i] = B[i]; return cntSubsequence(As, aa, Bs, bb, mem); } template R cntSubsequence(string A, string B, void *mem = wmem){ return cntSubsequence((int)A.size(), A.c_str(), (int)B.size(), B.c_str(), mem); } ------------------------------- isSubstring_string ------ int isSubstring(string A, string B, void *mem = wmem){ int i = 0, k, *fail; char *m; if(B.size() > A.size()) return 0; walloc1d(&fail, B.size()+1, &mem); k = fail[0] = -1; rep(i,B.size()){ while(k>=0 && B[k] != B[i]) k = fail[k]; fail[i+1] = ++k; } k = 0; rep(i,A.size()){ while(k >= 0 && B[k] != A[i]) k = fail[k]; if((++k) == B.size()) return 1; } return 0; } ------------------------------- isPalindrome ------ template inline int isPalindrome(const int N, const T A[]){ int i = 0, j = N-1; while(i < j){ if(A[i] != A[j]) return 0;; i++; j--; } return 1; } ------------------------------- longestSuffixPrefix ------ template int longestSuffixPrefix(int As, T A[], int Bs, T B[], void *mem = wmem){ int i, k, res; int *fail; if(As > Bs) A += As-Bs, As = Bs; if(As < Bs) Bs = As; walloc1d(&fail, Bs, &mem); k = fail[0] = -1; rep(i,Bs){ while(k>=0 && B[k]!=B[i]) k = fail[k]; fail[i+1] = ++k; } res = 0; rep(i,As){ while(res && A[i]!=B[res]) res = fail[res]; if(A[i]==B[res]) res++; } return res; } ------------------------------- strReplace1 ------ string strReplace_L(string str, string bef, string aft, void *mem = wmem){ int i = 0, k, *fail; char *m; string res; walloc1d(&fail, bef.size()+1, &mem); walloc1d(&m, str.size(), &mem); rep(i,str.size()) m[i] = 0; k = fail[0] = -1; rep(i,bef.size()){ while(k>=0 && bef[k] != bef[i]) k = fail[k]; fail[i+1] = ++k; } k = 0; rep(i,str.size()){ while(k >= 0 && bef[k] != str[i]) k = fail[k]; k++; if(k == bef.size()){ m[i-bef.size()+1] = 1; k = fail[k]; } } i = 0; while(i < str.size()){ if(m[i]){ res += aft; i += bef.size(); } else { res += str[i++]; } } return res; } ------------------------------- strReplace2 ------ string strReplace_L(string str, vector bef, vector aft, void *mem = wmem){ int i = 0, k, q, *fail, *m; string res; walloc1d(&fail, bef.size()+1, &mem); walloc1d(&m, str.size(), &mem); rep(i,str.size()) m[i] = -1; rrep(q,bef.size()){ k = fail[0] = -1; rep(i,bef[q].size()){ while(k>=0 && bef[q][k] != bef[q][i]) k = fail[k]; fail[i+1] = ++k; } k = 0; rep(i,str.size()){ while(k >= 0 && bef[q][k] != str[i]) k = fail[k]; k++; if(k == bef[q].size()){ m[i-bef[q].size()+1] = q; k = fail[k]; } } } i = 0; while(i < str.size()){ if(m[i] >= 0){ res += aft[m[i]]; i += bef[m[i]].size(); } else { res += str[i++]; } } return res; } ------------------------------- smallestSubsequenceLengthK ------ template void smallestSubsequenceLengthK(int N, T A[], int K, T res[], void *mem = wmem){ int i, d = N - K, s = 0; T *st; walloc1d(&st, N, &mem); rep(i,N){ while(s > 0 && d > 0 && A[i] < st[s-1]) s--, d--; st[s++] = A[i]; } rep(i,K) res[i] = st[i]; } ------------------------------- Trie ------ struct Trie{ int node, alphabet; int node_mem, alphabet_mem; int **nx; void init(const int k){ int i; node = 1; alphabet = k; rep(i,alphabet) nx[0][i] = -1; } void init(void){ init(alphabet_mem); } void malloc(const int n, const int k){ malloc2d(&nx,n,k); node_mem = n; alphabet_mem = k; init(); } void walloc(const int n, const int k, void **mem = &wmem){ walloc2d(&nx,n,k,mem); node_mem = n; alphabet_mem = k; init(); } void free(void){ free2d(nx); } template int addWord(const T word[], const int len){ int i, j, k, now = 0; rep(i,len){ if(nx[now][word[i]]==-1){ k = node++; nx[now][word[i]] = k; rep(j,alphabet) nx[k][j] = -1; } now = nx[now][word[i]]; } return now; } template inline int addNext(const int n, const T c){ int j, k; if(nx[n][c] != -1) return nx[n][c]; k = node++; nx[n][c] = k; rep(j,alphabet) nx[k][j] = -1; return k; } template inline int next(const int n, const T c){ return nx[n][c]; } }; ------------------------------- AhoCorasick ------ struct AhoCorasick{ int node, mem, alphabet; int **nx, *failed; int **ind, *indsz, *indmem; void init(void){ int i; node = 1; rep(i,alphabet) nx[0][i] = -1; failed[0] = 0; indsz[0] = 0; } void malloc(const int n, const int k){ int i; malloc2d(&nx,n,k); malloc1d(&failed,n); malloc1d(&ind,n); malloc1d(&indsz,n); malloc1d(&indmem,n); node = n; alphabet = k; rep(i,n) indmem[i] = 0; init(); } void free(void){ free2d(nx); free1d(failed); free1d(ind); free1d(indsz); free1d(indmem); } inline void addEnd(const int n, const int id){ int s; if(indsz[n]+1 > indmem[n]){ s = indmem[n] * 2 + 1; if(indmem[n]==0) ind[n] = (int*) std::malloc(s * sizeof(int)); else ind[n] = (int*) std::realloc(ind[n], s * sizeof(int)); indmem[n] = s; } ind[n][indsz[n]++] = id; } template int addWord(const T word[], const int len, int id){ int i, j, k, now = 0; rep(i,len){ if(nx[now][word[i]]==-1){ k = node++; nx[now][word[i]] = k; rep(j,alphabet) nx[k][j] = -1; indsz[k] = 0; } now = nx[now][word[i]]; } addEnd(now, id); return now; } void construct(void *mem = wmem){ int i, j, k, now; int *q, qs, qe; q = (int*) mem; qs = qe = 0; now = 0; rep(k,alphabet) if(nx[now][k] != -1){ q[qe++] = nx[now][k]; failed[ nx[now][k] ] = now; } while(qs < qe){ now = q[qs++]; rep(k,alphabet) if(nx[now][k] != -1){ i = failed[now]; while(i){ if(nx[i][k] != -1) break; i = failed[i]; } if(nx[i][k] != -1) i = nx[i][k]; failed[ nx[now][k] ] = i; rep(j,indsz[i]) addEnd(nx[now][k], ind[i][j]); q[qe++] = nx[now][k]; } } } template inline int next(const int n, const T c){ int i, now; now = n; if(nx[n][c]!=-1) return nx[n][c]; while(now && nx[now][c]==-1) now=failed[now]; if(nx[now][c]!=-1) now = nx[now][c]; return nx[n][c] = now; } }; ------------------------------- AhoCorasick_Sum ------ template struct AhoCorasick_Sum{ int node, mem, alphabet; int **nx, *failed; S *sum; void init(void){ int i; node = 1; rep(i,alphabet) nx[0][i] = -1; failed[0] = 0; sum[0] = 0; } void malloc(const int n, const int k){ int i; malloc2d(&nx,n,k); malloc1d(&failed,n); malloc1d(&sum,n); node = n; alphabet = k; init(); } void free(void){ free2d(nx); free1d(failed); free1d(sum); } template int addWord(const T word[], const int len, S val){ int i, j, k, now = 0; rep(i,len){ if(nx[now][word[i]]==-1){ k = node++; nx[now][word[i]] = k; rep(j,alphabet) nx[k][j] = -1; sum[k] = 0; } now = nx[now][word[i]]; } sum[now] += val; return now; } void construct(void *mem = wmem){ int i, j, k, now; int *q, qs, qe; q = (int*) mem; qs = qe = 0; now = 0; rep(k,alphabet) if(nx[now][k] != -1){ q[qe++] = nx[now][k]; failed[ nx[now][k] ] = now; } while(qs < qe){ now = q[qs++]; rep(k,alphabet) if(nx[now][k] != -1){ i = failed[now]; while(i){ if(nx[i][k] != -1) break; i = failed[i]; } if(nx[i][k] != -1) i = nx[i][k]; failed[ nx[now][k] ] = i; sum[ nx[now][k] ] += sum[i]; q[qe++] = nx[now][k]; } } } template inline int next(const int n, const T c){ int i, now; now = n; if(nx[n][c]!=-1) return nx[n][c]; while(now && nx[now][c]==-1) now=failed[now]; if(nx[now][c]!=-1) now = nx[now][c]; return nx[n][c] = now; } }; ------------------------------- twoMultisets ------ template struct twoMultisets{ multiset a, b; T sa, sb; twoMultisets(){ clear(); } void clear(){ a.clear(); b.clear(); sa = sb = 0; } void insert(T x){ if(b.size() == 0 || x < *b.begin()){ a.insert(x); sa += x; } else { b.insert(x); sb += x; } } int erase(T x){ typename multiset::iterator it; it = a.find(x); if(it != a.end()){ a.erase(it); sa -= x; return 1; } it = b.find(x); if(it != b.end()){ b.erase(it); sb -= x; return 1; } return 0; } int size(void){ return a.size() + b.size(); } T allsum(void){ return sa + sb; } void assign(int K){ T x; typename multiset::iterator it; while(a.size() < K){ x = *b.begin(); b.erase(b.begin()); a.insert(x); sa += x; sb -= x; } while(a.size() > K){ it = a.end(); it--; x = *it; a.erase(it); b.insert(x); sa -= x; sb += x; } } T Kth(int K){ assign(K); return *b.begin(); } T Ksum(int K){ assign(K); return sa; } T rKth(int K){ return Kth(a.size() + b.size() - K - 1); } T rKsum(int K){ assign(a.size() + b.size() - K); return sb; } T getMin(void){ if(a.size()) return *a.begin(); if(b.size()) return *b.begin(); return 0; } T getMin(T x){ if(a.size()) return *a.begin(); if(b.size()) return *b.begin(); return x; } T getMax(void){ if(b.size()) return *b.rbegin(); if(a.size()) return *a.rbegin(); return 0; } T getMax(T x){ if(b.size()) return *b.rbegin(); if(a.size()) return *a.rbegin(); return x; } }; ------------------------------- inversion_range ------ ll inversion_range(const int N, const int A[], const int mn, const int mx, void *mem=wmem){ int i, j, k; ll res = 0; fenwick t; t.walloc(mx-mn+1, &mem); t.init(mx-mn+1); for(i=N-1;i>=0;i--){ res += t.get(A[i]-mn-1); t.add(A[i]-mn,1); } return res; } ------------------------------- inversion ------ template ll inversion(const int N, const T A[], void *mem=wmem){ int i, j, k, p; int n1, n2; T *x, *y; ll res = 0; walloc1d(&x, N, &mem); walloc1d(&y, N, &mem); rep(i,N) x[i] = A[i]; for(k=0;k x[k+i]){ swap(x[k+i-1], x[k+i]); res++; } } } p = 4; while(p ll inversion(const vector &A, void *mem = wmem){ const int N = A.size(); int i, j, k, p; int n1, n2; T *x, *y; ll res = 0; walloc1d(&x, N, &mem); walloc1d(&y, N, &mem); rep(i,N) x[i] = A[i]; for(k=0;k x[k+i]){ swap(x[k+i-1], x[k+i]); res++; } } } p = 4; while(p ll inversion(const int N, const T A[], const T B[], void *mem = wmem){ int i, k, sz, *aa, *bb, *hist1, *hist2, **ind; walloc1d(&aa, N, &mem); walloc1d(&bb, N, &mem); sz = coordcomp(N,A,N,B,aa,bb,mem); if(sz > N) return -1; walloc1d(&hist1, sz, &mem); walloc1d(&hist2, sz, &mem); rep(i,sz) hist1[i] = 0; rep(i,sz) hist2[i] = 0; rep(i,N) hist1[aa[i]]++; rep(i,N) hist2[bb[i]]++; rep(i,sz) if(hist1[i] != hist2[i]) return -1; walloc1d(&ind, sz, &mem); rep(i,sz) walloc1d(&ind[i], hist2[i], &mem); rep(i,sz) hist2[i] = 0; rep(i,N){ k = bb[i]; ind[k][hist2[k]++] = i; } rrep(i,N){ k = aa[i]; aa[i] = ind[k][--hist1[k]]; } return inversion_range(N,aa,0,N-1,mem); } ------------------------------- ZetaTransform ------ template void ZetaTransform_L(int N, T A[], S res[]){ int i, j, x, m; rep(j,N) res[j] = A[j]; for(i=1;i void ZetaTransform(int N, T A[]){ int i, j, x, m; for(i=1;i void ZetaTransform_min_L(int N, T A[], S res[]){ int i, j, x, m; rep(j,N) res[j] = A[j]; for(i=1;i void ZetaTransform_min_L(int N, T A[]){ int i, j, x, m; for(i=1;i void ZetaTransform_min_L(int N, T A[], S r1[], S r2[]){ int i, j, k, x, m; rep(j,N) r1[j] = A[j]; rep(j,N) r2[j] = numeric_limits::max(); for(i=1;i void ZetaTransform_min_L(int N, T A[], S r1[], S r2[], S r3[]){ int i, j, k, x, m; rep(j,N) r1[j] = A[j]; rep(j,N) r2[j] = numeric_limits::max(); rep(j,N) r3[j] = numeric_limits::max(); for(i=1;i void ZetaTransform_max_L(int N, T A[], S res[]){ int i, j, x, m; rep(j,N) res[j] = A[j]; for(i=1;i?= res[x^i]; } } } template void ZetaTransform_max_L(int N, T A[]){ int i, j, x, m; for(i=1;i?= A[x^i]; } } } ------------------------------- MoebiusTransform ------ template void MoebiusTransform(int N, T A[], S res[]){ int i, j, x, m; rep(j,N) res[j] = A[j]; for(i=1;i void MoebiusTransform(int N, T A[]){ int i, j, x, m; for(i=1;i void ZetaTransform2(int N, T A[], S res[]){ int i, j, x, m; rep(j,N) res[j] = A[j]; for(i=1;i void ZetaTransform2(int N, T A[]){ int i, j, x, m; for(i=1;i void MoebiusTransform2(int N, T A[], S res[]){ int i, j, x, m; rep(j,N) res[j] = A[j]; for(i=1;i void MoebiusTransform2(int N, T A[]){ int i, j, x, m; for(i=1;i void HadamardTransform(int N, T A[]){ int i, j, k; T x, y; for(i=1;i void xorConvolution(int As, T1 A[], int Bs, T2 B[], int Rs, T3 R[], void *mem = wmem){ int i, n = 1, m; T1 *aa; T2 *bb; T3 iv; while(n < As) n *= 2; while(n < Bs) n *= 2; walloc1d(&aa, n, &mem); walloc1d(&bb, n, &mem); rep(i,As) aa[i] = A[i]; rep(i,As,n) aa[i] = 0; rep(i,Bs) bb[i] = B[i]; rep(i,Bs,n) bb[i] = 0; HadamardTransform(n,aa); HadamardTransform(n,bb); rep(i,n) aa[i] *= bb[i]; HadamardTransform(n,aa); iv = 1; iv /= n; m = min(Rs, n); rep(i,m) R[i] = aa[i] * iv; rep(i,m,Rs) R[i] = 0; } ------------------------------- orConvolution ------ template void orConvolution(int As, T1 A[], int Bs, T2 B[], int Rs, T3 R[], void *mem = wmem){ int i, n = 1, m; T1 *aa; T2 *bb; while(n < As) n *= 2; while(n < Bs) n *= 2; walloc1d(&aa, n, &mem); walloc1d(&bb, n, &mem); rep(i,As) aa[i] = A[i]; rep(i,As,n) aa[i] = 0; rep(i,Bs) bb[i] = B[i]; rep(i,Bs,n) bb[i] = 0; ZetaTransform(n,aa); ZetaTransform(n,bb); rep(i,n) aa[i] *= bb[i]; MoebiusTransform(n,aa); m = min(Rs, n); rep(i,m) R[i] = aa[i]; rep(i,m,Rs) R[i] = 0; } ------------------------------- andConvolution ------ template void andConvolution(int As, T1 A[], int Bs, T2 B[], int Rs, T3 R[], void *mem = wmem){ int i, n = 1, m; T1 *aa; T2 *bb; while(n < As) n *= 2; while(n < Bs) n *= 2; walloc1d(&aa, n, &mem); walloc1d(&bb, n, &mem); rep(i,As) aa[i] = A[i]; rep(i,As,n) aa[i] = 0; rep(i,Bs) bb[i] = B[i]; rep(i,Bs,n) bb[i] = 0; ZetaTransform2(n,aa); ZetaTransform2(n,bb); rep(i,n) aa[i] *= bb[i]; MoebiusTransform2(n,aa); m = min(Rs, n); rep(i,m) R[i] = aa[i]; rep(i,m,Rs) R[i] = 0; } ------------------------------- slideMin ------ template void slideMin(int n, int k, T in[], T res[], void *mem = wmem){ int i, s = 0; T *q; int q_st = 0, q_size = 0; walloc1d(&q, n); rep(i,n){ while(q_size && q[q_st+q_size-1] > in[i]) q_size--; q[q_st+q_size++] = in[i]; if(i>=k && in[i-k]==q[q_st]) q_st++, q_size--; if(i>=k-1) res[s++] = q[q_st]; } } ------------------------------- slideMax ------ template void slideMax(int n, int k, T in[], T res[], void *mem = wmem){ int i, s = 0; T *q; int q_st = 0, q_size = 0; walloc1d(&q, n); rep(i,n){ while(q_size && q[q_st+q_size-1] < in[i]) q_size--; q[q_st+q_size++] = in[i]; if(i>=k && in[i-k]==q[q_st]) q_st++, q_size--; if(i>=k-1) res[s++] = q[q_st]; } } ------------------------------- isLeapYear ------ template inline int isLeapYear(const T y){ if(y%4) return 0; if(y%100) return 1; if(y%400) return 0; return 1; } ------------------------------- numOfDaysInMonth1 ------ inline int numOfDaysInMonth(const int m){ if(m==2) return 28; if(m==4||m==6||m==9||m==11) return 30; return 31; } ------------------------------- numOfDaysInMonth2 ------ template inline int numOfDaysInMonth(const T y, const int m){ return numOfDaysInMonth(m) if[m==2, + isLeapYear(y)]; } ------------------------------- dayOfWeek ------ template inline int dayOfWeek(T Y, int M, int D){ int i, j; if(M <= 2) M += 12, Y--; i = (Y / 100) % 4; j = Y % 100; return (D + 13*(M+1)/5 + j + j/4 + 5*i + i/4 + 5) % 7; } ------------------------------- dayOfWeekStr ------ const char* WeekStr[7] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; inline const char* dayOfWeekStr(int w){ return WeekStr[w]; } template inline const char* dayOfWeekStr(T Y, int M, int D){ return WeekStr[dayOfWeek(Y, M, D)]; } ------------------------------- prevDay ------ template inline void prevDay(T &y, int &m, int &d){ d--; if(d==0){ m--; if(m==0) y--, m = 12; d = numOfDaysInMonth(y, m); } } ------------------------------- nextDay ------ template inline void nextDay(T &y, int &m, int &d){ d++; if(d > numOfDaysInMonth(y,m)){ d = 1; m++; if(m==13) m = 1, y++; } } ------------------------------- dayIndex ------ inline ll dayIndex(ll y, int m, int d){ static int sm[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; ll p, res = 1; p = (y-1) / 400; res += p * 146097; y -= p * 400; res += (y-1) * 365 + (y-1) / 4 - (y-1) / 100 + sm[m] + d-1; if(m >= 3 && isLeapYear(y)) res++; return res; } ------------------------------- dayFromIndex ------ template void dayFromIndex(S ind, T &y, int &m, int &d){ int i, k; static int mc[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; ind--; y = 1; y += (ind / 146097) * 400; ind %= 146097; y += (ind / 36524) * 100; ind %= 36524; y += (ind / 1461) * 4; ind %= 1461; rep(i,3) if(ind >= 365) ind -= 365, y++; rep(i,1,13){ k = mc[i]; if(i==2 && isLeapYear(y)) k++; if(ind < k){ m = i; d = ind + 1; break; } else { ind -= k; } } } ------------------------------- isVowel ------ inline int isVowel(const char c){ if(c=='a'||c=='i'||c=='u'||c=='e'||c=='o') return 1; if(c=='A'||c=='I'||c=='U'||c=='E'||c=='O') return 1; return 0; } ------------------------------- Arr1d ------ template struct Arr1d{ int n, mem; T *d; T& operator[](int a){ return d[a]; } void sort(){ reset(); std::sort(d, d+n); } ------------------------------- Arr1d_getSum ------ int set_cumulative_sum; int cumulative_sum_mem; T *cumulative_sum; void setSum(void){ int i; set_cumulative_sum = 1; if(cumulative_sum_mem < n+1){ delete[] cumulative_sum; cumulative_sum = new T[n+1]; cumulative_sum_mem = n+1; } cumulative_sum[0] = 0; rep(i,n) cumulative_sum[i+1] = cumulative_sum[i] + d[i]; } template T getSum(T1 i, T2 j){ if(i > j) return 0; if(set_cumulative_sum==0) setSum(); return cumulative_sum[min(j+1, n)] - cumulative_sum[max(0, i)]; } ------------------------------- Arr1d_ConstLenLeft ------ int set_const_len_left; int const_len_left_mem; int *const_len_left; void setConstLenLeft(void){ int i; set_const_len_left = 1; if(const_len_left_mem < n){ delete[] const_len_left; const_len_left = new int[n]; const_len_left_mem = n; } rep(i,n) const_len_left[i] = 1; rep(i,1,n) if(d[i]==d[i-1]) const_len_left[i] = const_len_left[i-1] + 1; } int ConstLenLeft(int st, T val){ if(!set_const_len_left) setConstLenLeft(); if(val != d[st]) return 0; return const_len_left[st]; } int ConstLenLeft(int st){ if(!set_const_len_left) setConstLenLeft(); return const_len_left[st]; } int ConstLenLeftCyclic(int st, T val){ if(!set_const_len_left) setConstLenLeft(); st %= n; if(st < 0) st += n; if(val != d[st]) return 0; if(const_len_left[st] != st+1 || d[st] != d[n-1]) return const_len_left[st]; if(const_len_left[n-1] == n) return int_inf; return const_len_left[st] + const_len_left[n-1]; } int ConstLenLeftCyclic(int st){ if(!set_const_len_left) setConstLenLeft(); st %= n; if(st < 0) st += n; if(const_len_left[st] != st+1 || d[st] != d[n-1]) return const_len_left[st]; if(const_len_left[n-1] == n) return int_inf; return const_len_left[st] + const_len_left[n-1]; } ------------------------------- Arr1d_ConstLenRight ------ int set_const_len_right; int const_len_right_mem; int *const_len_right; void setConstLenRight(void){ int i; set_const_len_right = 1; if(const_len_right_mem < n){ delete[] const_len_right; const_len_right = new int[n]; const_len_right_mem = n; } rep(i,n) const_len_right[i] = 1; rrep(i,n-1) if(d[i]==d[i+1]) const_len_right[i] = const_len_right[i+1] + 1; } int ConstLenRight(int st, T val){ if(!set_const_len_right) setConstLenRight(); if(val != d[st]) return 0; return const_len_right[st]; } int ConstLenRight(int st){ if(!set_const_len_right) setConstLenRight(); return const_len_right[st]; } int ConstLenRightCyclic(int st, T val){ if(!set_const_len_right) setConstLenRight(); if(val != d[st]) return 0; st %= n; if(st < 0) st += n; if(const_len_right[st] != n-st || d[st] != d[0]) return const_len_right[st]; if(const_len_right[0] == n) return int_inf; return const_len_right[st] + const_len_right[0]; } int ConstLenRightCyclic(int st){ if(!set_const_len_right) setConstLenRight(); st %= n; if(st < 0) st += n; if(const_len_right[st] != n-st || d[st] != d[0]) return const_len_right[st]; if(const_len_right[0] == n) return int_inf; return const_len_right[st] + const_len_right[0]; } ------------------------------- Arr1d_dHist ------ int set_dhist; int dhist_mem; int *dhist, *dhists; T dhist_mn, dhist_mx; void setDHist(void){ int i, len; set_dhist = 1; if(n==0) return; dhist_mn = dhist_mx = d[0]; rep(i,1,n){ if(dhist_mn > d[i]) dhist_mn = d[i]; if(dhist_mx < d[i]) dhist_mx = d[i]; } len = dhist_mx - dhist_mn + 1; if(dhist_mem < len){ delete[] dhist; dhist = new int[len]; delete[] dhists; dhists = new int[len+1]; dhist_mem = len; } rep(i,len) dhist[i] = 0; rep(i,n) dhist[d[i] - dhist_mn]++; dhists[0] = 0; rep(i,len) dhists[i+1] = dhists[i] + dhist[i]; } int dHist(T x){ if(set_dhist==0) setDHist(); if(n == 0 || x < dhist_mn || x > dhist_mx) return 0; return dhist[x - dhist_mn]; } int dHist(T x, T y){ if(set_dhist==0) setDHist(); if(x < dhist_mn) x = dhist_mn; if(y > dhist_mx) y = dhist_mx; if(n == 0 || x > y) return 0; return dhists[y-dhist_mn+1] - dhists[x-dhist_mn]; } ------------------------------- Arr1d_sHist ------ int set_shist; int shist_mem; T *shist; void setSHist(void){ int i; set_shist = 1; if(shist_mem < n){ delete[] shist; shist = new T[n]; shist_mem = n; } rep(i,n) shist[i] = d[i]; std::sort(shist, shist + n); } int sHist(T x){ if(set_shist==0) setSHist(); auto r = equal_range(shist, shist+n, x); return r.second - r.first; } int sHist(T x, T y){ if(set_shist==0) setSHist(); return upper_bound(shist, shist+n, y) - lower_bound(shist, shist+n, x); } ------------------------------- Arr1d_PrevLE ------ int set_prevLE; int prevLE_mem; int *prevLE; void setPrevLE(void *mem = wmem){ int i; int s = 0, *st; set_prevLE = 1; if(prevLE_mem < n){ delete[] prevLE; prevLE = new int[n]; prevLE_mem = n; } walloc1d(&st, n, &mem); rep(i,n){ while(s && d[st[s-1]] > d[i]) s--; if(s==0){ prevLE[i] = -1; } else { prevLE[i] = st[s-1]; } st[s++] = i; } } int PrevLE(int i){ if(set_prevLE==0) setPrevLE(); return prevLE[i]; } ------------------------------- Arr1d_PrevLT ------ int set_prevLT; int prevLT_mem; int *prevLT; void setPrevLT(void *mem = wmem){ int i; int s = 0, *st; set_prevLT = 1; if(prevLT_mem < n){ delete[] prevLT; prevLT = new int[n]; prevLT_mem = n; } walloc1d(&st, n, &mem); rep(i,n){ while(s && d[st[s-1]] >= d[i]) s--; if(s==0){ prevLT[i] = -1; } else { prevLT[i] = st[s-1]; } st[s++] = i; } } int PrevLT(int i){ if(set_prevLT==0) setPrevLT(); return prevLT[i]; } ------------------------------- Arr1d_PrevGE ------ int set_prevGE; int prevGE_mem; int *prevGE; void setPrevGE(void *mem = wmem){ int i; int s = 0, *st; set_prevGE = 1; if(prevGE_mem < n){ delete[] prevGE; prevGE = new int[n]; prevGE_mem = n; } walloc1d(&st, n, &mem); rep(i,n){ while(s && d[st[s-1]] < d[i]) s--; if(s==0){ prevGE[i] = -1; } else { prevGE[i] = st[s-1]; } st[s++] = i; } } int PrevGE(int i){ if(set_prevGE==0) setPrevGE(); return prevGE[i]; } ------------------------------- Arr1d_PrevGT ------ int set_prevGT; int prevGT_mem; int *prevGT; void setPrevGT(void *mem = wmem){ int i; int s = 0, *st; set_prevGT = 1; if(prevGT_mem < n){ delete[] prevGT; prevGT = new int[n]; prevGT_mem = n; } walloc1d(&st, n, &mem); rep(i,n){ while(s && d[st[s-1]] <= d[i]) s--; if(s==0){ prevGT[i] = -1; } else { prevGT[i] = st[s-1]; } st[s++] = i; } } int PrevGT(int i){ if(set_prevGT==0) setPrevGT(); return prevGT[i]; } ------------------------------- Arr1d_NextLE ------ int set_nextLE; int nextLE_mem; int *nextLE; void setNextLE(void *mem = wmem){ int i; int s = 0, *st; set_nextLE = 1; if(nextLE_mem < n){ delete[] nextLE; nextLE = new int[n]; nextLE_mem = n; } walloc1d(&st, n, &mem); rrep(i,n){ while(s && d[st[s-1]] > d[i]) s--; if(s==0){ nextLE[i] = n; } else { nextLE[i] = st[s-1]; } st[s++] = i; } } int NextLE(int i){ if(set_nextLE==0) setNextLE(); return nextLE[i]; } ------------------------------- Arr1d_NextLT ------ int set_nextLT; int nextLT_mem; int *nextLT; void setNextLT(void *mem = wmem){ int i; int s = 0, *st; set_nextLT = 1; if(nextLT_mem < n){ delete[] nextLT; nextLT = new int[n]; nextLT_mem = n; } walloc1d(&st, n, &mem); rrep(i,n){ while(s && d[st[s-1]] >= d[i]) s--; if(s==0){ nextLT[i] = n; } else { nextLT[i] = st[s-1]; } st[s++] = i; } } int NextLT(int i){ if(set_nextLT==0) setNextLT(); return nextLT[i]; } ------------------------------- Arr1d_NextGE ------ int set_nextGE; int nextGE_mem; int *nextGE; void setNextGE(void *mem = wmem){ int i; int s = 0, *st; set_nextGE = 1; if(nextGE_mem < n){ delete[] nextGE; nextGE = new int[n]; nextGE_mem = n; } walloc1d(&st, n, &mem); rrep(i,n){ while(s && d[st[s-1]] < d[i]) s--; if(s==0){ nextGE[i] = n; } else { nextGE[i] = st[s-1]; } st[s++] = i; } } int NextGE(int i){ if(set_nextGE==0) setNextGE(); return nextGE[i]; } ------------------------------- Arr1d_NextGT ------ int set_nextGT; int nextGT_mem; int *nextGT; void setNextGT(void *mem = wmem){ int i; int s = 0, *st; set_nextGT = 1; if(nextGT_mem < n){ delete[] nextGT; nextGT = new int[n]; nextGT_mem = n; } walloc1d(&st, n, &mem); rrep(i,n){ while(s && d[st[s-1]] <= d[i]) s--; if(s==0){ nextGT[i] = n; } else { nextGT[i] = st[s-1]; } st[s++] = i; } } int NextGT(int i){ if(set_nextGT==0) setNextGT(); return nextGT[i]; } ------------------------------- Arr1d_reset_head ------ void reset(){ ------------------------------- Arr1d_getSum_reset ------ set_cumulative_sum = 0; ------------------------------- Arr1d_ConstLenLeft_reset ------ set_const_len_left = 0; ------------------------------- Arr1d_ConstLenRight_reset ------ set_const_len_right = 0; ------------------------------- Arr1d_dHist_reset ------ set_dhist = 0; ------------------------------- Arr1d_sHist_reset ------ set_shist = 0; ------------------------------- Arr1d_PrevLE_reset ------ set_prevLE = 0; ------------------------------- Arr1d_PrevLT_reset ------ set_prevLT = 0; ------------------------------- Arr1d_PrevGE_reset ------ set_prevGE = 0; ------------------------------- Arr1d_PrevGT_reset ------ set_prevGT = 0; ------------------------------- Arr1d_NextLE_reset ------ set_nextLE = 0; ------------------------------- Arr1d_NextLT_reset ------ set_nextLT = 0; ------------------------------- Arr1d_NextGE_reset ------ set_nextGE = 0; ------------------------------- Arr1d_NextGT_reset ------ set_nextGT = 0; ------------------------------- Arr1d_reset_foot ------ } ------------------------------- Arr1d_constructor_head ------ void constructor(){ n = mem = 0; d = NULL; ------------------------------- Arr1d_getSum_constructor ------ set_cumulative_sum = 0; cumulative_sum_mem = 0; cumulative_sum = NULL; ------------------------------- Arr1d_ConstLenLeft_constructor ------ set_const_len_left = 0; const_len_left_mem = 0; const_len_left = NULL; ------------------------------- Arr1d_ConstLenRight_constructor ------ set_const_len_right = 0; const_len_right_mem = 0; const_len_right = NULL; ------------------------------- Arr1d_dHist_constructor ------ set_dhist = 0; dhist_mem = 0; dhist = NULL; dhists = NULL; ------------------------------- Arr1d_sHist_constructor ------ set_shist = 0; shist_mem = 0; shist = NULL; ------------------------------- Arr1d_PrevLE_constructor ------ set_prevLE = 0; prevLE_mem = 0; prevLE = NULL; ------------------------------- Arr1d_PrevLT_constructor ------ set_prevLT = 0; prevLT_mem = 0; prevLT = NULL; ------------------------------- Arr1d_PrevGE_constructor ------ set_prevGE = 0; prevGE_mem = 0; prevGE = NULL; ------------------------------- Arr1d_PrevGT_constructor ------ set_prevGT = 0; prevGT_mem = 0; prevGT = NULL; ------------------------------- Arr1d_NextLE_constructor ------ set_nextLE = 0; nextLE_mem = 0; nextLE = NULL; ------------------------------- Arr1d_NextLT_constructor ------ set_nextLT = 0; nextLT_mem = 0; nextLT = NULL; ------------------------------- Arr1d_NextGE_constructor ------ set_nextGE = 0; nextGE_mem = 0; nextGE = NULL; ------------------------------- Arr1d_NextGT_constructor ------ set_nextGT = 0; nextGT_mem = 0; nextGT = NULL; ------------------------------- Arr1d_constructor_foot ------ } ------------------------------- Arr1d_destructor_head ------ void destructor(){ delete[] d; d = NULL; mem = n = 0; ------------------------------- Arr1d_getSum_destructor ------ set_cumulative_sum = 0; cumulative_sum_mem = 0; delete[] cumulative_sum; cumulative_sum = NULL; ------------------------------- Arr1d_ConstLenLeft_destructor ------ set_const_len_left = 0; const_len_left_mem = 0; delete[] const_len_left; const_len_left = NULL; ------------------------------- Arr1d_ConstLenRight_destructor ------ set_const_len_right = 0; const_len_right_mem = 0; delete[] const_len_right; const_len_right = NULL; ------------------------------- Arr1d_dHist_destructor ------ set_dhist = 0; dhist_mem = 0; delete[] dhist; delete[] dhists; dhist = NULL; ------------------------------- Arr1d_sHist_destructor ------ set_shist = 0; shist_mem = 0; delete[] shist; shist = NULL; ------------------------------- Arr1d_PrevLE_destructor ------ set_prevLE = 0; prevLE_mem = 0; delete[] prevLE; prevLE = NULL; ------------------------------- Arr1d_PrevLT_destructor ------ set_prevLT = 0; prevLT_mem = 0; delete[] prevLT; prevLT = NULL; ------------------------------- Arr1d_PrevGE_destructor ------ set_prevGE = 0; prevGE_mem = 0; delete[] prevGE; prevGE = NULL; ------------------------------- Arr1d_PrevGT_destructor ------ set_prevGT = 0; prevGT_mem = 0; delete[] prevGT; prevGT = NULL; ------------------------------- Arr1d_NextLE_destructor ------ set_nextLE = 0; nextLE_mem = 0; delete[] nextLE; nextLE = NULL; ------------------------------- Arr1d_NextLT_destructor ------ set_nextLT = 0; nextLT_mem = 0; delete[] nextLT; nextLT = NULL; ------------------------------- Arr1d_NextGE_destructor ------ set_nextGE = 0; nextGE_mem = 0; delete[] nextGE; nextGE = NULL; ------------------------------- Arr1d_NextGT_destructor ------ set_nextGT = 0; nextGT_mem = 0; delete[] nextGT; nextGT = NULL; ------------------------------- Arr1d_destructor_foot ------ } ------------------------------- Arr1d_end ------ void constructor(int nn){ constructor(); malloc(nn); } void memory_expand(int nn){ if(mem < nn){ delete[] d; d = new T[nn]; mem = nn; } } void malloc(int nn){ reset(); memory_expand(nn); n = nn; } void setN(int nn){ reset(); memory_expand(nn); n = nn; } void setN(int nn, T val){ int i; reset(); memory_expand(nn); n = nn; rep(i,n) d[i] = val; } template void set(vector &a){ int i, nn = a.size(); setN(nn); rep(i,nn) d[i] = a[i]; } template void set_c(vector a){ int i, nn = a.size(); setN(nn); rep(i,nn) d[i] = a[i]; } template void set(int nn, S a[]){ int i; setN(nn); rep(i,nn) d[i] = a[i]; } void free(){ destructor(); } Arr1d(){ constructor(); } Arr1d(int nn){ constructor(nn); } ~Arr1d(){ destructor(); } }; ------------------------------- Arr2d ------ template struct Arr2d{ int n1, n2, mem1, mem2; T **d; T* operator[](int a){ return d[a]; } ------------------------------- Arr2d_getSum ------ int set_cumulative_sum; int cumulative_sum_mem1, cumulative_sum_mem2; T **cumulative_sum; void setSum(void){ int i, j; set_cumulative_sum = 1; if(cumulative_sum_mem1 < n1+1 || cumulative_sum_mem2 < n2+1){ rep(i,cumulative_sum_mem1) delete[] cumulative_sum[i]; delete[] cumulative_sum; cumulative_sum_mem1 = n1+1; cumulative_sum_mem2 = n2+1; cumulative_sum = new T*[cumulative_sum_mem1]; rep(i,cumulative_sum_mem1) cumulative_sum[i] = new T[cumulative_sum_mem2]; } rep(i,n1+1) cumulative_sum[i][0] = 0; rep(i,n2+1) cumulative_sum[0][i] = 0; rep(i,n1) rep(j,n2) cumulative_sum[i+1][j+1] = cumulative_sum[i+1][j] + cumulative_sum[i][j+1] - cumulative_sum[i][j] + d[i][j]; } template T getSum(T1 r1, T2 c1, T3 r2, T4 c2){ if(!set_cumulative_sum) setSum(); if(r1 > r2 || c1 > c2) return 0; r1 >?= 0; c1 >?= 0; r2 1 && c2 - c1 > 1) res -= cumulative_sum[r2][c2] - cumulative_sum[r2][c1+1] - cumulative_sum[r1+1][c2] + cumulative_sum[r1+1][c1+1]; return res; } ------------------------------- Arr2d_getSum45 ------ int set_cumulative_sum45; int cumulative_sum45_mem; T **cumulative_sum45; void setSum45(void){ int i, j; set_cumulative_sum45 = 1; if(cumulative_sum45_mem < n1+n2+1){ rep(i,cumulative_sum45_mem) delete[] cumulative_sum45[i]; delete[] cumulative_sum45; cumulative_sum45_mem = n1+n2+1; cumulative_sum45 = new T*[cumulative_sum45_mem]; rep(i,cumulative_sum45_mem) cumulative_sum45[i] = new T[cumulative_sum45_mem]; } rep(i,n1+n2+1) rep(j,n1+n2+1) cumulative_sum45[i][j] = 0; rep(i,n1) rep(j,n2) cumulative_sum45[n1-i+j][i+j+1] += d[i][j]; rep(i,n1+n2) rep(j,n1+n2) cumulative_sum45[i+1][j+1] += cumulative_sum45[i+1][j] + cumulative_sum45[i][j+1] - cumulative_sum45[i][j]; } T getSum45(int r1, int c1, int r2, int c2){ int x1, x2, y1, y2; if(!set_cumulative_sum45) setSum45(); x1 = n1 - 1 - r1 + c1; y1 = r1 + c1; x2 = n1 - 1 - r2 + c2; y2 = r2 + c2; if(x1 > x2) swap(x1, x2); if(y1 > y2) swap(y1, y2); return cumulative_sum45[x2+1][y2+1] - cumulative_sum45[x2+1][y1] - cumulative_sum45[x1][y2+1] + cumulative_sum45[x1][y1]; } T getSum45Border(int r1, int c1, int r2, int c2){ int x1, x2, y1, y2; T res; if(!set_cumulative_sum45) setSum45(); x1 = n1 - 1 - r1 + c1; y1 = r1 + c1; x2 = n1 - 1 - r2 + c2; y2 = r2 + c2; if(x1 > x2) swap(x1, x2); if(y1 > y2) swap(y1, y2); res = cumulative_sum45[x2+1][y2+1] - cumulative_sum45[x2+1][y1] - cumulative_sum45[x1][y2+1] + cumulative_sum45[x1][y1]; if(x2 - x1 > 1 && y2 - y1 > 1) res -= cumulative_sum45[x2][y2] - cumulative_sum45[x2][y1+1] - cumulative_sum45[x1+1][y2] + cumulative_sum45[x1+1][y1+1]; return res; } ------------------------------- Arr2d_ConstLenLeft ------ int set_const_len_left; int const_len_left_mem1, const_len_left_mem2; int **const_len_left; void setConstLenLeft(void){ int i, j; set_const_len_left = 1; if(const_len_left_mem1 < n1 || const_len_left_mem2 < n2){ rep(i,const_len_left_mem1) delete[] const_len_left[i]; delete[] const_len_left; const_len_left = new int*[n1]; rep(i,n1) const_len_left[i] = new int[n2]; const_len_left_mem1 = n1; const_len_left_mem2 = n2; } rep(i,n1) rep(j,n2) const_len_left[i][j] = 1; rep(i,n1) rep(j,1,n2) if(d[i][j]==d[i][j-1]) const_len_left[i][j] = const_len_left[i][j-1] + 1; } int ConstLenLeft(int i, int j, T val){ if(!set_const_len_left) setConstLenLeft(); if(val != d[i][j]) return 0; return const_len_left[i][j]; } int ConstLenLeft(int i, int j){ if(!set_const_len_left) setConstLenLeft(); return const_len_left[i][j]; } ------------------------------- Arr2d_ConstLenRight ------ int set_const_len_right; int const_len_right_mem1, const_len_right_mem2; int **const_len_right; void setConstLenRight(void){ int i, j; set_const_len_right = 1; if(const_len_right_mem1 < n1 || const_len_right_mem2 < n2){ rep(i,const_len_right_mem1) delete[] const_len_right[i]; delete[] const_len_right; const_len_right = new int*[n1]; rep(i,n1) const_len_right[i] = new int[n2]; const_len_right_mem1 = n1; const_len_right_mem2 = n2; } rep(i,n1) rep(j,n2) const_len_right[i][j] = 1; rep(i,n1) rrep(j,1,n2) if(d[i][j-1]==d[i][j]) const_len_right[i][j-1] = const_len_right[i][j] + 1; } int ConstLenRight(int i, int j, T val){ if(!set_const_len_right) setConstLenRight(); if(val != d[i][j]) return 0; return const_len_right[i][j]; } int ConstLenRight(int i, int j){ if(!set_const_len_right) setConstLenRight(); return const_len_right[i][j]; } ------------------------------- Arr2d_ConstLenUp ------ int set_const_len_up; int const_len_up_mem1, const_len_up_mem2; int **const_len_up; void setConstLenUp(void){ int i, j; set_const_len_up = 1; if(const_len_up_mem1 < n1 || const_len_up_mem2 < n2){ rep(i,const_len_up_mem1) delete[] const_len_up[i]; delete[] const_len_up; const_len_up = new int*[n1]; rep(i,n1) const_len_up[i] = new int[n2]; const_len_up_mem1 = n1; const_len_up_mem2 = n2; } rep(i,n1) rep(j,n2) const_len_up[i][j] = 1; rep(i,1,n1) rep(j,n2) if(d[i][j]==d[i-1][j]) const_len_up[i][j] = const_len_up[i-1][j] + 1; } int ConstLenUp(int i, int j, T val){ if(!set_const_len_up) setConstLenUp(); if(val != d[i][j]) return 0; return const_len_up[i][j]; } int ConstLenUp(int i, int j){ if(!set_const_len_up) setConstLenUp(); return const_len_up[i][j]; } ------------------------------- Arr2d_ConstLenDown ------ int set_const_len_down; int const_len_down_mem1, const_len_down_mem2; int **const_len_down; void setConstLenDown(void){ int i, j; set_const_len_down = 1; if(const_len_down_mem1 < n1 || const_len_down_mem2 < n2){ rep(i,const_len_down_mem1) delete[] const_len_down[i]; delete[] const_len_down; const_len_down = new int*[n1]; rep(i,n1) const_len_down[i] = new int[n2]; const_len_down_mem1 = n1; const_len_down_mem2 = n2; } rep(i,n1) rep(j,n2) const_len_down[i][j] = 1; rrep(i,1,n1) rrep(j,n2) if(d[i-1][j]==d[i][j]) const_len_down[i-1][j] = const_len_down[i][j] + 1; } int ConstLenDown(int i, int j, T val){ if(!set_const_len_down) setConstLenDown(); if(val != d[i][j]) return 0; return const_len_down[i][j]; } int ConstLenDown(int i, int j){ if(!set_const_len_down) setConstLenDown(); return const_len_down[i][j]; } ------------------------------- Arr2d_reset_head ------ void reset(){ ------------------------------- Arr2d_getSum_reset ------ set_cumulative_sum = 0; ------------------------------- Arr2d_getSum45_reset ------ set_cumulative_sum45 = 0; ------------------------------- Arr2d_ConstLenLeft_reset ------ set_const_len_left = 0; ------------------------------- Arr2d_ConstLenRight_reset ------ set_const_len_right = 0; ------------------------------- Arr2d_ConstLenUp_reset ------ set_const_len_up = 0; ------------------------------- Arr2d_ConstLenDown_reset ------ set_const_len_down = 0; ------------------------------- Arr2d_reset_foot ------ } ------------------------------- Arr2d_constructor_head ------ void constructor(){ n1 = n2 = mem1 = mem2 = 0; d = NULL; ------------------------------- Arr2d_getSum_constructor ------ set_cumulative_sum = 0; cumulative_sum_mem1 = cumulative_sum_mem2 = 0; cumulative_sum = NULL; ------------------------------- Arr2d_getSum45_constructor ------ set_cumulative_sum45 = 0; cumulative_sum45_mem = 0; cumulative_sum45 = NULL; ------------------------------- Arr2d_ConstLenLeft_constructor ------ set_const_len_left = 0; const_len_left_mem1 = const_len_left_mem2 = 0; const_len_left = NULL; ------------------------------- Arr2d_ConstLenRight_constructor ------ set_const_len_right = 0; const_len_right_mem1 = const_len_right_mem2 = 0; const_len_right = NULL; ------------------------------- Arr2d_ConstLenUp_constructor ------ set_const_len_up = 0; const_len_up_mem1 = const_len_up_mem2 = 0; const_len_up = NULL; ------------------------------- Arr2d_ConstLenDown_constructor ------ set_const_len_down = 0; const_len_down_mem1 = const_len_down_mem2 = 0; const_len_down = NULL; ------------------------------- Arr2d_constructor_foot ------ } ------------------------------- Arr2d_destructor_head ------ void destructor(){ int i; if(d != NULL){ rep(i,mem1) delete[] d[i]; delete[] d; } d = NULL; mem1 = mem2 = n1 = n2 = 0; ------------------------------- Arr2d_getSum_destructor ------ set_cumulative_sum = 0; if(cumulative_sum != NULL){ rep(i,cumulative_sum_mem1) delete[] cumulative_sum[i]; delete[] cumulative_sum; } cumulative_sum_mem1 = cumulative_sum_mem2 = 0; cumulative_sum = NULL; ------------------------------- Arr2d_getSum45_destructor ------ set_cumulative_sum45 = 0; if(cumulative_sum45 != NULL){ rep(i,cumulative_sum45_mem) delete[] cumulative_sum45[i]; delete[] cumulative_sum45; } cumulative_sum45_mem = 0; cumulative_sum45 = NULL; ------------------------------- Arr2d_ConstLenLeft_destructor ------ set_const_len_left = 0; if(const_len_left != NULL){ rep(i,const_len_left_mem1) delete[] const_len_left[i]; delete[] const_len_left; } const_len_left_mem1 = const_len_left_mem2 = 0; const_len_left = NULL; ------------------------------- Arr2d_ConstLenRight_destructor ------ set_const_len_right = 0; if(const_len_right != NULL){ rep(i,const_len_right_mem1) delete[] const_len_right[i]; delete[] const_len_right; } const_len_right_mem1 = const_len_right_mem2 = 0; const_len_right = NULL; ------------------------------- Arr2d_ConstLenUp_destructor ------ set_const_len_up = 0; if(const_len_up != NULL){ rep(i,const_len_up_mem1) delete[] const_len_up[i]; delete[] const_len_up; } const_len_up_mem1 = const_len_up_mem2 = 0; const_len_up = NULL; ------------------------------- Arr2d_ConstLenDown_destructor ------ set_const_len_down = 0; if(const_len_down != NULL){ rep(i,const_len_down_mem1) delete[] const_len_down[i]; delete[] const_len_down; } const_len_down_mem1 = const_len_down_mem2 = 0; const_len_down = NULL; ------------------------------- Arr2d_destructor_foot ------ } ------------------------------- Arr2d_end ------ void constructor(int nn1, int nn2){ constructor(); malloc(nn1, nn2); } void memory_expand(int nn1, int nn2){ int i; if(mem1 < nn1 || mem2 < nn2){ if(d != NULL){ rep(i,mem1) delete[] d[i]; delete[] d; } d = new T*[nn1]; rep(i,nn1) d[i] = new T[nn2]; mem1 = nn1; mem2 = nn2; } } void malloc(int nn1, int nn2){ reset(); memory_expand(nn1, nn2); n1 = nn1; n2 = nn2; } void setN(int nn1, int nn2){ reset(); memory_expand(nn1, nn2); n1 = nn1; n2 = nn2; } void setN(int nn1, int nn2, T val){ int i, j; reset(); memory_expand(nn1, nn2); n1 = nn1; n2 = nn2; rep(i,n1) rep(j,n2) d[i][j] = val; } template void set(vector> &a){ int i, j, nn1 = a.size(), nn2 = a[0].size(); setN(nn1, nn2); rep(i,nn1) rep(j,nn2) d[i][j] = a[i][j]; } template void set_c(vector> a){ int i, j, nn1 = a.size(), nn2 = a[0].size(); setN(nn1, nn2); rep(i,nn1) rep(j,nn2) d[i][j] = a[i][j]; } template void set(int nn1, int nn2, S **a){ int i, j; setN(nn1, nn2); rep(i,nn1) rep(j,nn2) d[i][j] = a[i][j]; } void free(){ destructor(); } Arr2d(){ constructor(); } Arr2d(int nn1, int nn2){ constructor(nn1, nn2); } ~Arr2d(){ destructor(); } }; ------------------------------- Grid1d ------ template struct Grid1d { int n; T *d; int set_s, set_d; T *d_s; int *up, *dw, *lf, *rg; void malloc(const int nn){ n = nn; set_s = 0; set_d = 0; malloc1d(&d, n); } void free(void){ free1d(d); if(set_s) free1d(d_s); if(set_d) free1d(up), free1d(dw); } T& operator[](int a){ return d[a]; } void setSum(void){ int i; if(set_s == 0){ set_s = 1; malloc1d(&d_s, n+1); } d_s[0] = 0; rep(i,n) d_s[i+1] = d_s[i] + d[i]; } void setDir(void){ int i; if(set_d == 0){ set_d = 1; malloc1d(&up, n); malloc1d(&dw, n); lf = dw; rg = up; } lf[0] = 1; rep(i,1,n) lf[i] = 1 if[d[i]==d[i-1], + lf[i-1]]; rg[n-1] = 1; for(i=n-2;i>=0;i--) rg[i] = 1 if[d[i]==d[i+1], + rg[i+1]]; } void setDirMatch(const T v){ int i; if(set_d == 0){ set_d = 1; malloc1d(&up, n); malloc1d(&dw, n); lf = dw; rg = up; } lf[0] = if[d[0]==v, 1, 0]; rep(i,1,n) lf[i] = if[d[i]==v, 1 + lf[i-1], 0]; rg[n-1] = if[d[n-1]==v, 1, 0]; for(i=n-2;i>=0;i--) rg[i] = if[d[i]==v, 1 + rg[i+1], 0]; } inline T getSum(const int a, const int b){ return d_s[b+1] - d_s[a]; } }; ------------------------------- Grid2d ------ template struct Grid2d { int r, c; T **d; int set_s, set_d; T **d_s; int **up, **dw, **lf, **rg; void malloc(const int rr, const int cc){ r = rr; c = cc; set_s = 0; set_d = 0; malloc2d(&d, r, c); } void free(void){ free2d(d); if(set_s) free2d(d_s); if(set_d) free2d(up), free2d(dw), free2d(lf), free2d(rg); } T*operator[](int a){ return d[a]; } void setSum(void){ int i, j; if(set_s == 0){ set_s = 1; malloc2d(&d_s, r+1, c+1); } rep(i,r+1) d_s[i][0] = 0; rep(j,c+1) d_s[0][j] = 0; rep(i,r) rep(j,c) d_s[i+1][j+1] = d_s[i][j+1] + d_s[i+1][j] - d_s[i][j] + d[i][j]; } void setDir(void){ int i, j; if(set_d == 0){ set_d = 1; malloc2d(&up, r, c); malloc2d(&dw, r, c); malloc2d(&lf, r, c); malloc2d(&rg, r, c); } rep(j,c) up[0][j] = 1; rep(i,1,r) rep(j,c) up[i][j] = 1 if[d[i][j]==d[i-1][j], + up[i-1][j]]; rep(j,c) dw[r-1][j] = 1; for(i=r-2;i>=0;i--) rep(j,c) dw[i][j] = 1 if[d[i][j]==d[i+1][j], + dw[i+1][j]]; rep(i,r){ lf[i][0] = 1; rep(j,1,c) lf[i][j] = 1 if[d[i][j]==d[i][j-1], + lf[i][j-1]]; } rep(i,r){ rg[i][c-1] = 1; for(j=c-2;j>=0;j--) rg[i][j] = 1 if[d[i][j]==d[i][j+1], + rg[i][j+1]]; } } void setDirMatch(const T v){ int i, j; if(set_d == 0){ set_d = 1; malloc2d(&up, r, c); malloc2d(&dw, r, c); malloc2d(&lf, r, c); malloc2d(&rg, r, c); } rep(j,c) up[0][j] = if[d[0][j]==v, 1, 0]; rep(i,1,r) rep(j,c) up[i][j] = if[d[i][j]==v, 1 + up[i-1][j], 0]; rep(j,c) dw[r-1][j] = if[d[r-1][j]==v, 1, 0]; for(i=r-2;i>=0;i--) rep(j,c) dw[i][j] = if[d[i][j]==v, 1 + dw[i+1][j], 0]; rep(i,r){ lf[i][0] = if[d[i][0]==v, 1, 0]; rep(j,1,c) lf[i][j] = if[d[i][j]==v, 1 + lf[i][j-1], 0]; } rep(i,r){ rg[i][c-1] = if[d[i][c-1]==v, 1, 0]; for(j=c-2;j>=0;j--) rg[i][j] = if[d[i][j]==v, 1 + rg[i][j+1], 0]; } } inline T getSum(const int r1, const int c1, const int r2, const int c2){ return d_s[r2+1][c2+1] - d_s[r1][c2+1] - d_s[r2+1][c1] + d_s[r1][c1]; } template inline void getDist4(int sr, int sc, S **res, void *mem = wmem){ int i, j, k; DijkstraHeap hp; hp.walloc(r*c); hp.init(r*c); if(d[sr][sc] >= 0) hp.change(sr*c+sc, d[sr][sc]); while(hp.size){ k = hp.pop(); i = k / c; j = k % c; if(i-1 >= 0 && d[i-1][j] >= 0) hp.change((i-1)*c+j, hp.val[k]+d[i-1][j]); if(i+1 < r && d[i+1][j] >= 0) hp.change((i+1)*c+j, hp.val[k]+d[i+1][j]); if(j-1 >= 0 && d[i][j-1] >= 0) hp.change(i*c+(j-1), hp.val[k]+d[i][j-1]); if(j+1 < c && d[i][j+1] >= 0) hp.change(i*c+(j+1), hp.val[k]+d[i][j+1]); } rep(i,r) rep(j,c) res[i][j] = if[hp.visited[i*c+j], hp.val[i*c+j], -1]; } template inline void getDist4_BFS(int sr, int sc, S **res, void *mem = wmem){ int i, j, k; int *q, qs=0, qe=0; walloc1d(&q,r*c,&mem); rep(i,r) rep(j,c) res[i][j] = -1; if(d[sr][sc] >= 0) res[sr][sc] = 1; q[qe++] = sr*c+sc; while(qs < qe){ k = q[qs++]; i = k / c; j = k % c; if(i-1 >= 0 && d[i-1][j] >= 0 && res[i-1][j]==-1) res[i-1][j] = res[i][j] + 1, q[qe++] = (i-1)*c + j; if(i+1 < r && d[i+1][j] >= 0 && res[i+1][j]==-1) res[i+1][j] = res[i][j] + 1, q[qe++] = (i+1)*c + j; if(j-1 >= 0 && d[i][j-1] >= 0 && res[i][j-1]==-1) res[i][j-1] = res[i][j] + 1, q[qe++] = i*c + (j-1); if(j+1 < c && d[i][j+1] >= 0 && res[i][j+1]==-1) res[i][j+1] = res[i][j] + 1, q[qe++] = i*c + (j+1); } } }; ------------------------------- fft ------ struct fft_pnt{ double x, y; fft_pnt(void){ } fft_pnt(double a, double b){ x = a; y = b; } void set(double a, double b){ x = a; y = b; } fft_pnt& operator+=(fft_pnt a){ x+=a.x; y+=a.y; return *this; } fft_pnt& operator-=(fft_pnt a){ x-=a.x; y-=a.y; return *this; } fft_pnt& operator*=(fft_pnt a){ fft_pnt p = *this; x = p.x*a.x-p.y*a.y; y = p.x*a.y+p.y*a.x; return *this; } fft_pnt operator+(fft_pnt a){ return fft_pnt(*this) += a; } fft_pnt operator-(fft_pnt a){ return fft_pnt(*this) -= a; } fft_pnt operator*(fft_pnt a){ return fft_pnt(*this) *= a; } }; void fft(int n, fft_pnt x[], void *mem = wmem){ int i, j; int n1, n2, n3, step = 1; double theta = 2*PI / n, tmp; fft_pnt w1, w2, w3, a, b, c, d, aa, bb, cc, dd, *y = (fft_pnt*)mem; while(n > 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; rep(i,n1){ w1 = fft_pnt(cos(i*theta),-sin(i*theta)); w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = b - d; tmp = dd.y; dd.y = dd.x; dd.x = -tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb - dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb + dd); } } n /= 4; step *= 4; theta *= 4; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; theta *= 2; swap(x,y); } rep(i,step) y[i] = x[i]; } void fftinv(int n, fft_pnt x[], void *mem = wmem){ int i, j; int n1, n2, n3, step = 1; double theta = 2*PI / n, tmp; fft_pnt w1, w2, w3, a, b, c, d, aa, bb, cc, dd, *y = (fft_pnt*)mem; while(n > 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; rep(i,n1){ w1 = fft_pnt(cos(i*theta),sin(i*theta)); w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = b - d; tmp = dd.y; dd.y = dd.x; dd.x = -tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb + dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb - dd); } } n /= 4; step *= 4; theta *= 4; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; theta *= 2; swap(x,y); } rep(i,step) y[i] = x[i]; } ------------------------------- convolution ------ void convolution_L(double A[], int As, double B[], int Bs, double res[], int Rs, void *mem = wmem){ int i, n, n2; double mul; fft_pnt *a, *b; n = max(As+Bs, Rs); for(n2=1;n2 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; w1.val = mint::R; rep(i,n1){ w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = (b - d) * tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb - dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb + dd); } w1 *= root; } n /= 4; step *= 4; root *= root; root *= root; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; root *= root; swap(x,y); } rep(i,step) y[i] = x[i]; } void fftinv(int n, mint x[], mint root = MD_PRIMITIVE_ROOT, void *mem = wmem){ int i, j; int n1, n2, n3, step = 1; mint w1, w2, w3, a, b, c, d, aa, bb, cc, dd, tmp, *y; walloc1d(&y, n, &mem); root = root.inverse(); tmp = root.pw((mint::md-1)/4); root = root.pw((mint::md-1)/n); while(n > 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; w1.val = mint::R; rep(i,n1){ w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = (b - d) * tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb + dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb - dd); } w1 *= root; } n /= 4; step *= 4; root *= root; root *= root; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; root *= root; swap(x,y); } rep(i,step) y[i] = x[i]; } ------------------------------- convolution-mint ------ void convolution_L(mint A[], int As, mint B[], int Bs, mint res[], int Rs, mint root = MD_PRIMITIVE_ROOT, void *mem = wmem){ int i, n, n2; mint *a, *b, r; n = max(As+Bs, Rs); for(n2=1;n2 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; w1.val = MINT_R; rep(i,n1){ w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = (b - d) * tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb - dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb + dd); } w1 *= root; } n /= 4; step *= 4; root *= root; root *= root; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; root *= root; swap(x,y); } rep(i,step) y[i] = x[i]; } void fftinv(int n, Mint x[], Mint root = MD_PRIMITIVE_ROOT, void *mem = wmem){ int i, j; int n1, n2, n3, step = 1; Mint w1, w2, w3, a, b, c, d, aa, bb, cc, dd, tmp, *y; walloc1d(&y, n, &mem); root = root.inverse(); tmp = root.pw((MD-1)/4); root = root.pw((MD-1)/n); while(n > 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; w1.val = MINT_R; rep(i,n1){ w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = (b - d) * tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb + dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb - dd); } w1 *= root; } n /= 4; step *= 4; root *= root; root *= root; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; root *= root; swap(x,y); } rep(i,step) y[i] = x[i]; } ------------------------------- convolution-Mint ------ void convolution_L(Mint A[], int As, Mint B[], int Bs, Mint res[], int Rs, Mint root = MD_PRIMITIVE_ROOT, void *mem = wmem){ int i, n, n2; Mint *a, *b, r; n = max(As+Bs, Rs); for(n2=1;n2 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; w1.val = 1; rep(i,n1){ w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = (b - d) * tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb - dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb + dd); } w1 *= root; } n /= 4; step *= 4; root *= root; root *= root; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; root *= root; swap(x,y); } rep(i,step) y[i] = x[i]; } void fftinv(int n, modint x[], modint root = MD_PRIMITIVE_ROOT, void *mem = wmem){ int i, j; int n1, n2, n3, step = 1; modint w1, w2, w3, a, b, c, d, aa, bb, cc, dd, tmp, *y; walloc1d(&y, n, &mem); root = root.inverse(); tmp = root.pw((modint::md-1)/4); root = root.pw((modint::md-1)/n); while(n > 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; w1.val = 1; rep(i,n1){ w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = (b - d) * tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb + dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb - dd); } w1 *= root; } n /= 4; step *= 4; root *= root; root *= root; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; root *= root; swap(x,y); } rep(i,step) y[i] = x[i]; } ------------------------------- convolution-modint ------ void convolution_L(modint A[], int As, modint B[], int Bs, modint res[], int Rs, modint root = MD_PRIMITIVE_ROOT, void *mem = wmem){ int i, n, n2; modint *a, *b, r; n = max(As+Bs, Rs); for(n2=1;n2 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; w1.val = 1; rep(i,n1){ w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = (b - d) * tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb - dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb + dd); } w1 *= root; } n /= 4; step *= 4; root *= root; root *= root; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; root *= root; swap(x,y); } rep(i,step) y[i] = x[i]; } void fftinv(int n, Modint x[], Modint root = MD_PRIMITIVE_ROOT, void *mem = wmem){ int i, j; int n1, n2, n3, step = 1; Modint w1, w2, w3, a, b, c, d, aa, bb, cc, dd, tmp, *y; walloc1d(&y, n, &mem); root = root.inverse(); tmp = root.pw((MD-1)/4); root = root.pw((MD-1)/n); while(n > 2){ n1 = n / 4; n2 = n1 + n1; n3 = n1 + n2; w1.val = 1; rep(i,n1){ w2 = w1*w1; w3 = w1*w2; rep(j,step){ a = x[j+step*i]; b = x[j+step*(i+n1)]; c = x[j+step*(i+n2)]; d = x[j+step*(i+n3)]; aa = a + c; bb = a - c; cc = b + d; dd = (b - d) * tmp; y[j+step*(4*i )] = aa + cc; y[j+step*(4*i+1)] = w1*(bb + dd); y[j+step*(4*i+2)] = w2*(aa - cc); y[j+step*(4*i+3)] = w3*(bb - dd); } w1 *= root; } n /= 4; step *= 4; root *= root; root *= root; swap(x,y); } if(n==2){ rep(i,step){ y[i] = x[i] + x[i+step]; y[i+step] = x[i] - x[i+step]; } n /= 2; step *= 2; root *= root; swap(x,y); } rep(i,step) y[i] = x[i]; } ------------------------------- convolution-Modint ------ void convolution_L(Modint A[], int As, Modint B[], int Bs, Modint res[], int Rs, Modint root = MD_PRIMITIVE_ROOT, void *mem = wmem){ int i, n, n2; Modint *a, *b, r; n = max(As+Bs, Rs); for(n2=1;n2 T Hungarian(T **mat, int n, int m, int match[] = NULL, void *mem = wmem){ int i, a, b, c, r, z; int *toright; int *toleft; T *ofsleft; T *ofsright; int *left, *right; int *trace, *ptr; T d, t, res = 0; walloc1d(&toright, n, &mem); walloc1d(&toleft, m, &mem); walloc1d(&ofsleft, n, &mem); walloc1d(&ofsright, m, &mem); walloc1d(&left, n, &mem); walloc1d(&right, m, &mem); walloc1d(&trace, m, &mem); walloc1d(&ptr, m, &mem); rep(i,n) toright[i] = -1, ofsleft[i] = 0; rep(i,m) toleft[i] = -1, ofsright[i] = 0; rep(r,n){ rep(i,n) left[i] = 0; rep(i,m) right[i] = 0; rep(i,m) trace[i] = -1, ptr[i] = r; left[r] = 1; for(;;){ d = std::numeric_limits::max(); rep(i,m) if(!right[i]){ t = mat[ptr[i]][i] + ofsleft[ptr[i]] + ofsright[i]; if(d > t) d = t, b = i; } res += d; rep(i,n) if(left[i]) ofsleft[i] -= d; rep(i,m) if(right[i]) ofsright[i] += d; trace[b] = ptr[b]; c = toleft[b]; if(c < 0){ while(b>=0){ a = trace[b]; z = toright[a]; toleft[b] = a; toright[a] = b; b = z; } break; } right[b] = left[c] = 1; rep(i,m) if(mat[c][i] + ofsleft[c] + ofsright[i] < mat[ptr[i]][i] + ofsleft[ptr[i]] + ofsright[i]) ptr[i] = c; } } if(match!=NULL) rep(i,n) match[i] = toright[i]; return res; } ------------------------------- polationVal ------ template T polationVal(int n, T x[], T y[], T t){ int i, j; T res, tmp; rep(i,n) if(x[i]==t) return y[i]; res = 0; rep(i,n){ tmp = 1; rep(j,n) if(i!=j) tmp *= x[i] - x[j]; tmp = 1 / tmp; rep(j,n) if(i!=j) tmp *= t - x[j]; res += y[i] * tmp; } return res; } template T polationVal(int n, T y[], T t, void *mem = wmem){ int i, j; T res, m, *ifac, *lf, *rg; if(n==1) return y[0]; rep(i,n) if(t==i) return y[i]; walloc1d(&ifac, n+1); walloc1d(&lf, n+1); walloc1d(&rg, n+1); ifac[0] = ifac[1] = m = 1; rep(i,2,n+1) m *= i; m = ifac[n] = 1 / m; rrep(i,2,n) ifac[i] = ifac[i+1] * (i+1); lf[0] = 1; rep(i,n) lf[i+1] = lf[i] * (t-i); rg[0] = 1; rep(i,n) rg[i+1] = rg[i] * (t-(n-1-i)); if(n%2==0) m = -m; res = 0; rep(i,n){ m *= i - n; res -= y[i] * lf[i] * rg[n-1-i] * m * ifac[i]; } return res; } ------------------------------- polationPoly ------ template Polynomial polationPoly_L(int n, T x[], T y[]){ int i, j; T c; Polynomial res, tmp, t1; tmp.change(0, 1); t1.change(1, 1); rep(i,n){ t1.change(0, -x[i]); tmp *= t1; } rep(i,n){ c = 1; rep(j,n) if(j!=i) c *= (x[i] - x[j]); c = y[i] / c; t1.change(0, -x[i]); res += c * tmp / t1; } return res; } ------------------------------- Explode ------ vector Explode_L(const string &str, const string &d){ int s = 0, i = 0, j; vector res; while(i + d.size() - 1 < str.size()){ rep(j,d.size()) if(str[i+j] != d[j]) break; if(j != d.size()) i++, continue; res.push_back(str.substr(s, i-s)); s = (i += d.size()); } res.push_back(str.substr(s)); return res; } ------------------------------- Implode ------ string Implode_L(const vector &v, const string &d){ int i; string res; if(v.size()==0) return res; res += v[0]; rep(i,1,v.size()){ res += d; res += v[i]; } return res; } ------------------------------- knightDistance ------ template inline T knightDistance(T x, T y){ T res; if(x < 0) x = -x; if(y < 0) y = -y; if(x+y==1) return 3; if(x==y==2) return 4; res = max( x/+2, y/+2, (x+y)/+3 ); if(res%2 != (x+y)%2) res++; return res; } ------------------------------- InnerProd_1 ------ template S InnerProd_L(int n, S a[]){ S res = 0; rep(i,n) res += a[i]; return res; } ------------------------------- InnerProd_2 ------ template S InnerProd_L(int n, S a[], T b[]){ S res = 0; rep(i,n) res += a[i] * b[i]; return res; } ------------------------------- InnerProd_3 ------ template S InnerProd_L(int n, S a[], T b[], U c[]){ S res = 0; rep(i,n) res += a[i] * b[i] * c[i]; return res; } ------------------------------- InnerProd_4 ------ template S InnerProd_L(int n, S a[], T b[], U c[], V d[]){ S res = 0; rep(i,n) res += a[i] * b[i] * c[i] * d[i]; return res; } ------------------------------- crossProd ------ ll crossProd_L(ll x1, ll y1, ll x2, ll y2){ return x1 * y2 - x2 * y1; } ------------------------------- LineIntersection_size ------ int LineIntersection_size_L(ll x1, ll y1, ll x2, ll y2, ll x3, ll y3, ll x4, ll y4, int p1 = 1, int p2 = 1, int p3 = 1, int p4 = 1){ ll a, b, dx1, dy1, dx2, dy2; if(p1 == p3 == 2){ dx1 = x2 - x1; dy1 = y2 - y1; if(dx1 < 0) dx1 = -dx1, dy1 = -dy1; dx2 = x4 - x3; dy2 = y4 - y3; if(dx2 < 0) dx2 = -dx2, dy2 = -dy2; a = gcd(dx1, abs(dy1)); dx1 /= a; dy1 /= a; a = gcd(dx2, abs(dy2)); dx2 /= a; dy2 /= a; if(dx1!=dx2 || dy1 != dy2) return 1; a = crossProd(x2-x1, y2-y1, x3-x1, y3-y1); if(a==0) return 2; return 0; } if(p3 == 2){ swap(x1, x3); swap(y1, y3); swap(p1, p3); swap(x2, x4); swap(y2, y4); swap(p2, p4); } a = crossProd(x2-x1, y2-y1, x3-x1, y3-y1); b = crossProd(x2-x1, y2-y1, x4-x1, y4-y1); if(a==b==0){ if(p1==2) return 2; if(x1==x2==x3==x4) x1 = y1, x2 = y2, x3 = y3, x4 = y4; if(x1 > x2) swap(x1, x2), swap(p1, p2); if(x3 > x4) swap(x3, x4), swap(p3, p4); if(x2 == x3 && p2 == p3 == 1) return 1; if(x4 == x1 && p4 == p1 == 1) return 1; if(x2 < x3 || x4 < x1) return 0; return 2; } if(a > b) a = -a, b = -b; if(a > 0 || (p3==0 && a >= 0)) return 0; if(b < 0 || (p4==0 && b <= 0)) return 0; if(p1==2) return 1; a = crossProd(x4-x3, y4-y3, x1-x3, y1-y3); b = crossProd(x4-x3, y4-y3, x2-x3, y2-y3); if(a > b) a = -a, b = -b; if(a > 0 || (p1==0 && a >= 0)) return 0; if(b < 0 || (p2==0 && b <= 0)) return 0; return 1; } ------------------------------- dimcomp2 ------ struct dimcomp2 { int B; dimcomp2(){} dimcomp2(int b){ B = b; } dimcomp2(int a, int b){ B = b; } inline void set(int b){ B = b; } inline void set(int a, int b){ B = b; } inline int mask(int a, int b){ return a * B + b; } inline int operator()(int a, int b){ return a * B + b; } inline void para(int mask, int &a, int &b){ a = mask / B; b = mask % B; } inline void operator()(int mask, int &a, int &b){ a = mask / B; b = mask % B; } }; ------------------------------- dimcomp3 ------ struct dimcomp3 { int B, C; dimcomp3(){}; dimcomp3(int b, int c){ B = b; C = c; } dimcomp3(int a, int b, int c){ B = b; C = c; } inline void set(int b, int c){ B = b; C = c; } inline void set(int a, int b, int c){ B = b; C = c; } inline int mask(int a, int b, int c){ return (a * B + b) * C + c; } inline int operator()(int a, int b, int c){ return (a * B + b) * C + c; } inline void para(int mask, int &a, int &b, int &c){ a = mask / (B*C); b = mask % (B*C) / C; c = mask % C; } inline void operator()(int mask, int &a, int &b, int &c){ a = mask / (B*C); b = mask % (B*C) / C; c = mask % C; } }; ------------------------------- dimcomp4 ------ struct dimcomp4 { int B, C, D; dimcomp4(){} dimcomp4(int b, int c, int d){ B = b; C = c; D = d; } dimcomp4(int a, int b, int c, int d){ B = b; C = c; D = d; } inline void set(int b, int c, int d){ B = b; C = c; D = d; } inline void set(int a, int b, int c, int d){ B = b; C = c; D = d; } inline int operator()(int a, int b, int c, int d){ return ((a * B + b) * C + c) * D + d; } inline int mask(int a, int b, int c, int d){ return ((a * B + b) * C + c) * D + d; } inline void operator()(int mask, int &a, int &b, int &c, int &d){ a = mask / (B*C*D); b = mask % (B*C*D) / (C*D); c = mask % (C*D) / D; d = mask % D; } inline void para(int mask, int &a, int &b, int &c, int &d){ a = mask / (B*C*D); b = mask % (B*C*D) / (C*D); c = mask % (C*D) / D; d = mask % D; } }; ------------------------------- HammingDistance ------ template int HammingDistance(int N, S A[], T B[]){ int i, res = 0; rep(i,N) if(A[i] != B[i]) res++; return res; } ------------------------------- editDistance ------ template int editDistance(int As, T A[], int Bs, T B[], void *mem = wmem){ int i, j, k, *dp; walloc1d(&dp, (As+1)*(Bs+1), &mem); rep(i,As+1) dp[i*(Bs+1)] = i; rep(i,Bs+1) dp[i] = i; REP(i,1,As+1) REP(j,1,Bs+1){ k = min(dp[i*(Bs+1)+j-1], dp[(i-1)*(Bs+1)+j]) + 1; if(A[i-1]==B[j-1]) k = min(k, dp[(i-1)*(Bs+1)+(j-1)]); else k = min(k, dp[(i-1)*(Bs+1)+(j-1)]+1); dp[i*(Bs+1)+j] = k; } return dp[As*(Bs+1)+Bs]; } ------------------------------- counterSumIsLT ------ template ll counterSumIsLT(int As, T A[], int Bs, T B[], T val){ int i = 0, j = Bs; ll res = 0; while(i < As){ while(j && A[i] + B[j-1] >= val) j--; if(!j) break; while(i ll counterProdIsLT(int As, T A[], int Bs, T B[], T val){ int i, j; int ma = 0, za = 0, pa = 0; int mb = 0, zb = 0, pb = 0; ll res = 0; i = 0; while(i < As && A[i] < 0) i++; ma = i; while(i < As && A[i] == 0) i++; za = i - ma; pa = As - i; i = 0; while(i < Bs && B[i] < 0) i++; mb = i; while(i < Bs && B[i] == 0) i++; zb = i - mb; pb = Bs - i; if(val < 0){ j = 0; rep(i,pa){ while(j < mb && A[As-pa+i] * B[j] < val) j++; res += j; } j = 0; rep(i,pb){ while(j < ma && B[Bs-pb+i] * A[j] < val) j++; res += j; } } else if(val == 0){ res = (ll) ma * pb + (ll) pa * mb; } else { res = (ll) As * Bs - (ll) pa * pb - (ll) ma * mb; j = pb; rep(i,pa){ while(j && A[As-pa+i] * B[Bs-pb+j-1] >= val) j--; if(j==0) break; res += j; } j = mb; rep(i,ma){ while(j && A[ma-1-i] * B[mb-j] >= val) j--; if(j==0) break; res += j; } } return res; } ------------------------------- counterD2SumIsLT ------ template ll counterD2SumIsLT(int As, T A[], T val){ int i = 0, j = As - 1; ll res = 0; while(i < j){ while(i < j && A[i] + A[j] >= val) j--; if(i >= j) break; while(i < j && A[i] + A[j] < val) res += j - i, i++; } return res; } ------------------------------- counterM2SumIsLT ------ template ll counterM2SumIsLT(int As, T A[], T val){ int i = 0, j = As - 1; ll res = 0; while(i <= j){ while(i <= j && A[i] + A[j] >= val) j--; if(i > j) break; while(i <= j && A[i] + A[j] < val) res += j - i + 1, i++; } return res; } ------------------------------- counterD2ProdIsLT ------ template ll counterD2ProdIsLT(int As, T A[], T val){ int i, j; int ma = 0, za = 0, pa = 0; ll res = 0; i = 0; while(i < As && A[i] < 0) i++; ma = i; while(i < As && A[i] == 0) i++; za = i - ma; pa = As - i; if(val < 0){ j = 0; rep(i,pa){ while(j < ma && A[As-pa+i] * A[j] < val) j++; res += j; } } else if(val == 0){ res = (ll) ma * pa; } else { res = (ll) As * (As - 1) / 2 - (ll) pa * (pa - 1) / 2 - (ll) ma * (ma - 1) / 2; j = pa; rep(i,pa){ while(j - 1 > i && A[As-pa+i] * A[As-pa+j-1] >= val) j--; if(j - 1 <= i) break; res += j - i - 1; } j = ma; rep(i,ma){ while(j - 1 > i && A[ma-1-i] * A[ma-j] >= val) j--; if(j - 1 <= i) break; res += j - i - 1; } } return res; } ------------------------------- counterM2ProdIsLT ------ template ll counterM2ProdIsLT(int As, T A[], T val){ int i, j; int ma = 0, za = 0, pa = 0; ll res = 0; i = 0; while(i < As && A[i] < 0) i++; ma = i; while(i < As && A[i] == 0) i++; za = i - ma; pa = As - i; if(val < 0){ j = 0; rep(i,pa){ while(j < ma && A[As-pa+i] * A[j] < val) j++; res += j; } } else if(val == 0){ res = (ll) ma * pa; } else { res = (ll) As * (As + 1) / 2 - (ll) pa * (pa + 1) / 2 - (ll) ma * (ma + 1) / 2; j = pa; rep(i,pa){ while(j - 1 >= i && A[As-pa+i] * A[As-pa+j-1] >= val) j--; if(j - 1 < i) break; res += j - i; } j = ma; rep(i,ma){ while(j - 1 >= i && A[ma-1-i] * A[ma-j] >= val) j--; if(j - 1 < i) break; res += j - i; } } return res; } ------------------------------- rangeTree2d ------ template struct rangeTree2d{ int N, N2; int *sz; S *tot; fenwick *w; T1 **d1, *ddd1; T2 *d2; inline void build(int nn, T1 dd1[], T2 dd2[], S ww[] = NULL, void **mem = &wmem){ int i, j, i1, i2, k1, k2, s, s1, s2; S *www; int *ind; N = nn; for(N2=1;N2 struct rangeTree2d_nw{ int N, N2; int *sz; T1 **d1; T2 *d2; inline void build(int nn, T1 dd1[], T2 dd2[], void **mem = &wmem){ int i, j, i1, i2, k1, k2, s, s1, s2; T1 *ddd1; N = nn; for(N2=1;N2 struct segtree_ph_inRT{ int N, logN; T *val; void malloc(int maxN, int once = 0); void walloc(int maxN, void **mem = &wmem); void walloc(int maxN, int once = 0, void **mem = &wmem); void free(void); T& operator[](int i); void setN(int n, int zerofill = 1, int dobuild = 1); void build(void); inline void build(int a); inline void change(int a, T v); inline void add(int a, T v); inline T get(int a, int b); }; template struct rangeTree2d_pf{ int N, N2; int *sz; S *tot, defval; segtree_ph_inRT *w; T1 **d1, *ddd1; T2 *d2; inline void build(int nn, T1 dd1[], T2 dd2[], S ww[] = NULL, void **mem = &wmem); inline void change(T1 x, T2 y, S v); inline void add(T1 x, T2 y, S v); inline void setDefault(const S val){ defval = val; } inline S query(T1 x1, T1 x2, T2 y1, T2 y2); }; ------------------------------- rangeTree2d_pf ------ template void segtree_ph_inRT::malloc(int maxN, int once /*= 0*/){ int i; for(i=1;i void segtree_ph_inRT::walloc(int maxN, void **mem /*= &wmem*/){ int i; for(i=1;i void segtree_ph_inRT::walloc(int maxN, int once /*= 0*/, void **mem /*= &wmem*/){ int i; for(i=1;i void segtree_ph_inRT::free(void){ delete [] val; } template T& segtree_ph_inRT::operator[](int i){ return val[N+i]; } template void segtree_ph_inRT::setN(int n, int zerofill /*= 1*/, int dobuild /*= 1*/){ int i; for(i=1,logN=0;i void segtree_ph_inRT::build(void){ for(int i=N-1;i;i--) val[i] = rangeTree2d_pf_func(val[2i], val[2i+1]); } template inline void segtree_ph_inRT::build(int a){ while(a > 1){ a /= 2; val[a] = rangeTree2d_pf_func(val[2a], val[2a+1]); } } template inline void segtree_ph_inRT::change(int a, T v){ val[a+N] = v; build(a+N); } template inline void segtree_ph_inRT::add(int a, T v){ val[a+N] += v; build(a+N); } template inline T segtree_ph_inRT::get(int a, int b){ T res, tmp; int fga = 0, fgb = 0; a += N; b += N; while(a < b){ if(a%2){ if(fga){ res = rangeTree2d_pf_func(res, val[a]); } else { res = val[a]; fga = 1; } a++; } if(b%2){ b--; if(fgb){ tmp = rangeTree2d_pf_func(val[b], tmp); } else { tmp = val[b]; fgb = 1; } } a /= 2; b /= 2; } if(fga==1 && fgb==0) return res; if(fga==0 && fgb==1) return tmp; if(fga==1 && fgb==1) return rangeTree2d_pf_func(res, tmp); return res; } template inline void rangeTree2d_pf::build(int nn, T1 dd1[], T2 dd2[], S ww[]/* = NULL*/, void **mem /* = &wmem*/){ int i, j, i1, i2, k1, k2, s, s1, s2; S *www; int *ind; N = nn; for(N2=1;N2 inline void rangeTree2d_pf::change(T1 x, T2 y, S v){ int a, b, z; a = lower_bound(d2, d2+N, y) - d2; b = upper_bound(d2, d2+N, y) - d2; z = lower_bound(ddd1+a, ddd1+b, x) - ddd1 + N2; while(z){ a = lower_bound(d1[z], d1[z]+sz[z], x) - d1[z]; w[z].change(a, v); z /= 2; } } template inline void rangeTree2d_pf::add(T1 x, T2 y, S v){ int a, b, z; a = lower_bound(d2, d2+N, y) - d2; b = upper_bound(d2, d2+N, y) - d2; z = lower_bound(ddd1+a, ddd1+b, x) - ddd1 + N2; while(z){ a = lower_bound(d1[z], d1[z]+sz[z], x) - d1[z]; w[z].add(a, v); z /= 2; } } template inline S rangeTree2d_pf::query(T1 x1, T1 x2, T2 y1, T2 y2){ S res; int a, b, z1, z2, fg = 0; a = lower_bound(d2, d2+N, y1) - d2 + N2; b = lower_bound(d2, d2+N, y2) - d2 + N2; while(a < b){ if(a%2){ z1 = lower_bound(d1[a], d1[a]+sz[a], x1) - d1[a]; z2 = lower_bound(d1[a], d1[a]+sz[a], x2) - d1[a]; if(z1 < z2){ if(fg == 0){ fg = 1; res = w[a].get(z1,z2); } else { res = rangeTree2d_pf_func(res, w[a].get(z1,z2)); } } a++; } if(b%2){ b--; z1 = lower_bound(d1[b], d1[b]+sz[b], x1) - d1[b]; z2 = lower_bound(d1[b], d1[b]+sz[b], x2) - d1[b]; if(z1 < z2){ if(fg == 0){ fg = 1; res = w[b].get(z1,z2); } else { res = rangeTree2d_pf_func(res, w[b].get(z1,z2)); } } } a /= 2; b /= 2; } if(!fg) return defval; return res; } ------------------------------- Permutation ------ struct Permutation { int n, mem; int *dat; Permutation(){n = mem = 0;} Permutation(const int nn){ n = mem = nn; if(mem > 0) dat = new int[mem]; } Permutation(const Permutation &a){ int i; mem = n = a.n; dat = new int[mem]; rep(i,mem) dat[i] = a.dat[i]; } ~Permutation(){ if(mem) delete [] dat; } void changeSize(const int nn){ n = nn; if(mem < n){ if(mem) delete [] dat; mem = n; dat = new int[mem]; } } Permutation& operator=(const Permutation &a){ int i; changeSize(a.n); n = a.n; rep(i,n) dat[i] = a.dat[i]; return *this; } Permutation& operator=(const int a){ int i; rep(i,n) dat[i] = i; return *this; } Permutation& operator*=(const Permutation &a){ int i, *m; void *mv = wmem; if(n==0 || n!=a.n){ changeSize(0); return *this; } walloc1d(&m, n, &mv); rep(i,n) m[i] = dat[a.dat[i]]; rep(i,n) dat[i] = m[i]; return *this; } Permutation operator*(const Permutation &a){ return Permutation(*this) *= a; } bool operator==(const Permutation &a){ int i; if(n != a.n) return false; rep(i,n) if(dat[i] != a.dat[i]) return false; return true; } template void apply(T A[]){ int i; T *B; void *mv = wmem; walloc1d(&B, n, &mv); rep(i,n) B[dat[i]] = A[i]; rep(i,n) A[i] = B[i]; } template void apply(T A[], T B[]){ int i; rep(i,n) B[dat[i]] = A[i]; } int cycle_len(int res[] = NULL){ int i, j, k, sz = 0; int *vis; void *mv = wmem; if(res==NULL) walloc1d(&res, n, &mv); walloc1d(&vis, n, &mv); rep(i,n) vis[i] = 0; rep(i,n) if(!vis[i]){ k = 0; j = i; while(vis[j]==0){ vis[j] = 1; j = dat[j]; k++; } res[sz++] = k; } return sz; } void cycle_len_EachElement(int res[]){ int i, j, k, sz = 0; int *vis; void *mv = wmem; walloc1d(&vis, n, &mv); rep(i,n) vis[i] = 0; rep(i,n) if(!vis[i]){ k = 0; j = i; while(vis[j]==0){ vis[j] = 1; j = dat[j]; k++; } j = i; while(vis[j]==1){ res[j] = k; vis[j] = 2; j = dat[j]; } } } template inline T getIndex(void *mem = wmem){ int i; fenwick t; T res, *fac; walloc1d(&fac,n,&mem); fac[0] = 1; rep(i,1,n) fac[i] = i * fac[i-1]; t.walloc(n,&mem); t.init(n); rep(i,n) t.add(i,1); res = 0; rep(i,n){ t.add(dat[i], -1); res += fac[n-1-i] * t.get(dat[i]-1); } return res; } inline int& operator[](const int a){ return dat[a]; } }; template inline Permutation pow_L(Permutation a, S b){ Permutation res; res.changeSize(a.n); res = 1; while(b){ if(b&1) res *= a; b >>= 1; a *= a; } return res; } ------------------------------- IntMap ------ struct IntMap { int n, mem, logn; int *dat; int **nx, calc_nx; int numCycle, *cycleLen, **cycle; int *int2c, *int2cInd; IntMap(){ n = mem = logn = 0; calc_nx = 0; numCycle = 0; } IntMap(int nn){ n = mem = nn; for(logn=0; (1< 0) dat = new int[mem]; calc_nx = 0; numCycle = 0; } ~IntMap(){ if(mem) delete[] dat; if(calc_nx){ rep(i,logn) delete[] nx[i]; delete[] nx; } if(numCycle > 0){ delete[] cycleLen; rep(i,numCycle) delete[] cycle[i]; delete[] cycle; delete[] int2c; delete[] int2cInd; } } void changeSize(const int nn){ int old_logn = logn; n = nn; for(logn=0; (1< 0){ delete[] cycleLen; rep(i,numCycle) delete[] cycle[i]; delete[] cycle; delete[] int2c; delete[] int2cInd; numCycle = 0; } } int calcCycle(void){ int i, j, k; if(numCycle){ delete[] cycleLen; rep(i,numCycle) delete[] cycle[i]; delete[] cycle; delete[] int2c; delete[] int2cInd; numCycle = 0; } int2c = new int[n]; int2cInd = new int[n]; rep(i,n) int2c[i] = -2; rep(i,n) int2cInd[i] = -1; numCycle = 0; rep(i,n) if(int2c[i] == -2){ j = i; for(;;){ if(int2c[j] != -2) break; int2c[j] = -3; j = dat[j]; } if(int2c[j] == -3){ k = 0; for(;;){ if(int2c[j] != -3) break; int2c[j] = numCycle; int2cInd[j] = k++; j = dat[j]; } numCycle++; } j = i; for(;;){ if(int2c[j] != -3) break; int2c[j] = -1; j = dat[j]; } } cycleLen = new int[numCycle]; rep(i,numCycle) cycleLen[i] = 0; rep(i,n) if(int2c[i] >= 0) cycleLen[int2c[i]]++; cycle = new int*[numCycle]; rep(i,numCycle) cycle[i] = new int[cycleLen[i]]; rep(i,n) if(int2c[i] >= 0) cycle[int2c[i]][int2cInd[i]] = i; return numCycle; } void calcNext(int recalc = 1){ if(recalc || numCycle==0) calcCycle(); if(calc_nx == 0){ calc_nx = 1; nx = new int*[logn]; rep(i,logn) nx[i] = new int[n]; } rep(i,n) nx[0][i] = dat[i]; rep(k,1,logn) rep(i,n) nx[k][i] = nx[k-1][nx[k-1][i]]; } template int getNext(int x, T s){ if(calc_nx==0) calcNext(); if(s >= (1<<(logn-1))){ x = nx[logn-1][x]; s -= (1<<(logn-1)); return cycle[int2c[x]][(int2cInd[x]+s)%cycleLen[int2c[x]]]; } rep(i,logn) if(s&1< T TSP_cycle(int n, T **dist, void *mem = wmem){ const T m = numeric_limits::max(); int i, j, ii, jj, mask; int as, bs, *a, *b; T **dp, res = m; if(n==1) return 0; n--; walloc2d(&dp, n, 1< T TSP_path(int n, T **dist, void *mem = wmem){ const T m = numeric_limits::max(); int i, j, ii, jj, mask; int as, bs, *a, *b; T **dp, res = m; if(n==1) return 0; walloc2d(&dp, n, 1< T TSP_path_s(int n, T **dist, int s = 0, void *mem = wmem){ const T m = numeric_limits::max(); int i, j, ii, jj, mask; int as, bs, *a, *b; T **dp, **d, res = m; if(n==1) return 0; walloc2d(&d, n, n, &mem); rep(i,n) rep(j,n){ if(i < s) ii = i; if(j < s) jj = j; if(i == s) ii = n - 1; if(j == s) jj = n - 1; if(i > s) ii = i - 1; if(j > s) jj = j - 1; d[ii][jj] = dist[i][j]; } n--; walloc2d(&dp, n, 1<> 61) + (r & ROLLING_HASH_MOD); if(a >= ROLLING_HASH_MOD) a -= ROLLING_HASH_MOD; return a; } inline ull rollingHash61_pow(ull a, ull b){ ull r = 1; for(;;){ if(b&1){ r = rollingHash61_mul(r, a); } if(b==0) break; b >>= 1; a = rollingHash61_mul(a, a); } return r; } void rollingHashInit(){ int i; Rand rnd; ull x; rep(i,20) rnd.get(2); do{ x = rnd.get(1.0, (double)(ROLLING_HASH_MOD-2)); }while(gcd(x,ROLLING_HASH_MOD-1) != 1); ROLLING_HASH_BASE = rollingHash61_pow(ROLLING_HASH_PRIMITIVE_ROOT, x); ROLLING_HASH_IBASE = rollingHash61_pow(ROLLING_HASH_BASE, ROLLING_HASH_MOD - 2); } void rollingHash_expand(int k){ int i; if(ROLLING_HASH_MEM >= k) return; ROLLING_HASH_MEM = max(2 * ROLLING_HASH_MEM, k); assert(ROLLING_HASH_MEM <= 2 * ROLLING_HASH_MAX_MEMORY); ROLLING_HASH_PW = (ull*) realloc(ROLLING_HASH_PW, ROLLING_HASH_MEM * sizeof(ull)); ROLLING_HASH_IPW = (ull*) realloc(ROLLING_HASH_IPW, ROLLING_HASH_MEM * sizeof(ull)); ROLLING_HASH_PW[0] = 1; rep(i,1,ROLLING_HASH_MEM) ROLLING_HASH_PW[i] = rollingHash61_mul(ROLLING_HASH_PW[i-1], ROLLING_HASH_BASE); ROLLING_HASH_IPW[0] = 1; rep(i,1,ROLLING_HASH_MEM) ROLLING_HASH_IPW[i] = rollingHash61_mul(ROLLING_HASH_IPW[i-1], ROLLING_HASH_IBASE); } struct rollingHash{ ll len; ull hs; template void set(int N, T A[]){ int i; ll tmp; hs = 0; len = N; rollingHash_expand(N); rep(i,N){ tmp = A[i] % ((ll)ROLLING_HASH_MOD); if(tmp < 0) tmp += ROLLING_HASH_MOD; hs += rollingHash61_mul(tmp, ROLLING_HASH_PW[i]); if(hs >= ROLLING_HASH_MOD) hs -= ROLLING_HASH_MOD; } } template void change(ll ind, S bef, T aft){ ll tmp1, tmp2; tmp1 = bef % ((ll)ROLLING_HASH_MOD); tmp2 = aft % ((ll)ROLLING_HASH_MOD); tmp1 = tmp2 - tmp1; if(tmp1 < 0) tmp1 += ROLLING_HASH_MOD; if(tmp1 < 0) tmp1 += ROLLING_HASH_MOD; if(tmp1 >= ROLLING_HASH_MOD) tmp1 -= ROLLING_HASH_MOD; if(ind+1 <= ROLLING_HASH_MAX_MEMORY || ind+1 >= ROLLING_HASH_MEM){ rollingHash_expand(ind+1); hs += rollingHash61_mul(tmp1, ROLLING_HASH_PW[ind]); } else { hs += rollingHash61_mul(tmp1, rollingHash61_pow(ROLLING_HASH_BASE, ind)); } if(hs >= ROLLING_HASH_MOD) hs -= ROLLING_HASH_MOD; } void push_front(rollingHash a){ if(a.len + 1 <= ROLLING_HASH_MAX_MEMORY || a.len + 1 >= ROLLING_HASH_MEM){ rollingHash_expand(a.len + 1); hs = rollingHash61_mul(hs, ROLLING_HASH_PW[a.len]); } else { hs = rollingHash61_mul(hs, rollingHash61_pow(ROLLING_HASH_BASE, a.len)); } hs += a.hs; if(hs >= ROLLING_HASH_MOD) hs -= ROLLING_HASH_MOD; len += a.len; } void push_back(rollingHash a){ if(len + 1 <= ROLLING_HASH_MAX_MEMORY || len + 1 >= ROLLING_HASH_MEM){ rollingHash_expand(len + 1); hs += rollingHash61_mul(a.hs, ROLLING_HASH_PW[len]); } else { hs += rollingHash61_mul(a.hs, rollingHash61_pow(ROLLING_HASH_BASE, len)); } if(hs >= ROLLING_HASH_MOD) hs -= ROLLING_HASH_MOD; len += a.len; } void pop_front(rollingHash a){ if(hs >= a.hs){ hs -= a.hs; } else { hs = hs + ROLLING_HASH_MOD - a.hs; } if(a.len + 1 <= ROLLING_HASH_MAX_MEMORY || a.len + 1 >= ROLLING_HASH_MEM){ rollingHash_expand(a.len + 1); hs = rollingHash61_mul(hs, ROLLING_HASH_IPW[a.len]); } else { hs = rollingHash61_mul(hs, rollingHash61_pow(ROLLING_HASH_IBASE, a.len)); } len -= a.len; } void pop_back(rollingHash a){ ull tmp; if(len + 1 <= ROLLING_HASH_MAX_MEMORY || len + 1 >= ROLLING_HASH_MEM){ rollingHash_expand(len + 1); tmp = rollingHash61_mul(a.hs, ROLLING_HASH_PW[len]); } else { tmp = rollingHash61_mul(a.hs, rollingHash61_pow(ROLLING_HASH_BASE, len)); } if(hs >= tmp){ hs -= tmp; } else { hs = hs + ROLLING_HASH_MOD - tmp; } len -= a.len; } bool operator==(const rollingHash a){ return len == a.len && hs == a.hs; } bool operator!=(const rollingHash a){ return len != a.len || hs != a.hs; } }; template rollingHash calcRollingHash(int N, T A[]){ rollingHash res; res.set(N, A); return res; } struct rollingHashSubarrays{ ull *hs; int mem, len; void set(){ hs = NULL; mem = len = 0; } void free(){ if(mem) delete[] hs; } void expand(int k){ if(mem >= k) return; free(); mem = max(2*mem, k); hs = new ull[mem]; } template void set(int N, T A[]){ int i; ll tmp; if(N <= 0) return; rollingHash_expand(N); expand(N); len = N; tmp = A[0] % ((ll)ROLLING_HASH_MOD); if(tmp < 0) tmp += ROLLING_HASH_MOD; hs[0] = tmp; rep(i,1,N){ tmp = A[i] % ((ll)ROLLING_HASH_MOD); if(tmp < 0) tmp += ROLLING_HASH_MOD; hs[i] = hs[i-1] + rollingHash61_mul(tmp, ROLLING_HASH_PW[i]); if(hs[i] >= ROLLING_HASH_MOD) hs[i] -= ROLLING_HASH_MOD; } } rollingHash get_len(int s, int len){ ull x; rollingHash res; res.len = len; rollingHash_expand(s+1); if(s == 0){ res.hs = hs[len-1]; } else { if(hs[s+len-1] >= hs[s-1]){ res.hs = hs[s+len-1] - hs[s-1]; } else { res.hs = hs[s+len-1] + ROLLING_HASH_MOD - hs[s-1]; } res.hs = rollingHash61_mul(res.hs, ROLLING_HASH_IPW[s]); } return res; } rollingHash get(int a, int b){ return get_len(a, b - a + 1); } rollingHashSubarrays(){ set(); } ~rollingHashSubarrays(){ free(); } }; ------------------------------- HashMap_init ------ { int i, j, k; Rand rnd; rep(i,20) rnd.get(2); rep(i,4){ rep(j,32){ k = rnd.get(1,62); HashMap_ullP_L[i] |= (1ULL << k); } HashMap_ullP_L[i] |= (1ULL << 0); HashMap_ullP_L[i] |= (1ULL << 63); } } ------------------------------- HashMap ------ ull HashMap_ullP_L[4]; template struct HashMap{ char *used; KEY *key; VAL *val; int mem, n, mask; int init_flag; VAL init_val; HashMap(){ mem = 0; init_flag = 0; } ~HashMap(){ free(); } void expand(int nn){ if(mem >= nn) return; if(mem) free(); mem = nn; used = new char[nn]; key = new KEY[nn]; val = new VAL[nn]; } void free(){ if(mem){ mem = 0; delete[] used; delete[] key; delete[] val; } } void init(int nn){ n = 1; nn = nn + (nn + 1) / 2; while(n < nn) n *= 2; mask = n - 1; expand(n); rep(i,n) used[i] = 0; init_flag = 0; } void init(int nn, VAL ini){ n = 1; nn = nn + (nn + 1) / 2; while(n < nn) n *= 2; mask = n - 1; expand(n); rep(i,n) used[i] = 0; init_flag = 1; init_val = ini; } inline int getHash(const int a){ ull d = a; d = (((d * HashMap_ullP_L[0]) >> 32) * HashMap_ullP_L[1]) & mask; return d; } inline int getHash(const unsigned a){ ull d = a; d = (((d * HashMap_ullP_L[0]) >> 32) * HashMap_ullP_L[1]) & mask; return d; } inline int getHash(const ll a){ ull d = a; d = (((((d * HashMap_ullP_L[0]) >> 32) * HashMap_ullP_L[1]) >> 32) * HashMap_ullP_L[2]) & mask; return d; } inline int getHash(const ull a){ ull d = a; d = (((((d * HashMap_ullP_L[0]) >> 32) * HashMap_ullP_L[1]) >> 32) * HashMap_ullP_L[2]) & mask; return d; } inline int getHash(const pair a){ ull d = (((ull)a.first) << 32) + ((ull)a.second); d = (((((d * HashMap_ullP_L[0]) >> 32) * HashMap_ullP_L[1]) >> 32) * HashMap_ullP_L[2]) & mask; return d; } inline VAL& operator[](const KEY a){ int k = getHash(a); for(;;){ if(used[k]==1 && key[k]==a) break; if(used[k]==0){ used[k] = 1, key[k] = a; if(init_flag) val[k] = init_val; break; } k = (k+1) & mask; } return val[k]; } inline bool exist(const KEY a){ int k = getHash(a); for(;;){ if(used[k]==1 && key[k]==a) return true; if(used[k]==0) break; k = (k+1) & mask; } return false; } template inline bool exist(const KEY a, S &res){ int k = getHash(a); for(;;){ if(used[k]==1 && key[k]==a) res = val[k], return true; if(used[k]==0) break; k = (k+1) & mask; } return false; } }; ------------------------------- subsetSum ------ template int subsetSum(int n, T a[], S res[]){ int i, k, sz = 1; res[0] = 0; rep(k,n){ rep(i,sz) res[sz+i] = res[i] + a[k]; sz *= 2; } return sz; } ------------------------------- subsetSumS ------ template int subsetSumS(int n, T a[], S res[], void *mem = wmem){ int i, k, sz = 1, bf, x, y; S *arr; walloc1d(&arr, 1, &mem); res[0] = 0; rep(k,n){ bf = sz; sz = x = y = 0; rep(i,bf) arr[i] = res[i]; rep(i,bf) arr[bf+i] = res[i] + a[k]; while(x < bf && y < bf){ if(arr[x] < arr[bf+y]){ res[sz++] = arr[x]; x++; } else { res[sz++] = arr[bf+y]; y++; } } while(x < bf){ res[sz++] = arr[x]; x++; } while(y < bf){ res[sz++] = arr[bf+y]; y++; } } return sz; } template int subsetSumS(int n, T a[], S res[], U lim, void *mem = wmem){ int i, k, sz = 1, bf, x, y; S *arr; walloc1d(&arr, 1, &mem); res[0] = 0; rep(k,n){ bf = sz; sz = x = y = 0; rep(i,bf) arr[i] = res[i]; rep(i,bf) arr[bf+i] = res[i] + a[k]; while(x < bf && y < bf){ if(arr[x] < arr[bf+y]){ res[sz++] = arr[x]; x++; } else { res[sz++] = arr[bf+y]; y++; } } while(x < bf){ res[sz++] = arr[x]; x++; } while(y < bf){ res[sz++] = arr[bf+y]; y++; } while(sz && res[sz-1] > lim) sz--; } return sz; } ------------------------------- subsetSumSD ------ template int subsetSumSD(int n, T a[], S res[], void *mem = wmem){ int i, k, sz = 1, bf, x, y; S *arr; walloc1d(&arr, 1, &mem); res[0] = 0; rep(k,n){ bf = sz; sz = x = y = 0; rep(i,bf) arr[i] = res[i]; rep(i,bf) arr[bf+i] = res[i] + a[k]; while(x < bf && y < bf){ if(arr[x] < arr[bf+y]){ if(sz==0 || res[sz-1]!=arr[x]) res[sz++] = arr[x]; x++; } else { if(sz==0 || res[sz-1]!=arr[bf+y]) res[sz++] = arr[bf+y]; y++; } } while(x < bf){ if(sz==0 || res[sz-1]!=arr[x]) res[sz++] = arr[x]; x++; } while(y < bf){ if(sz==0 || res[sz-1]!=arr[bf+y]) res[sz++] = arr[bf+y]; y++; } } return sz; } template int subsetSumSD(int n, T a[], S res[], U lim, void *mem = wmem){ int i, k, sz = 1, bf, x, y; S *arr; walloc1d(&arr, 1, &mem); res[0] = 0; rep(k,n){ bf = sz; sz = x = y = 0; rep(i,bf) arr[i] = res[i]; rep(i,bf) arr[bf+i] = res[i] + a[k]; while(x < bf && y < bf){ if(arr[x] < arr[bf+y]){ if(sz==0 || res[sz-1]!=arr[x]) res[sz++] = arr[x]; x++; } else { if(sz==0 || res[sz-1]!=arr[bf+y]) res[sz++] = arr[bf+y]; y++; } } while(x < bf){ if(sz==0 || res[sz-1]!=arr[x]) res[sz++] = arr[x]; x++; } while(y < bf){ if(sz==0 || res[sz-1]!=arr[bf+y]) res[sz++] = arr[bf+y]; y++; } while(sz && res[sz-1] > lim) sz--; } return sz; } ------------------------------- maxSubsetDP ------ template void maxSubsetDP(int N, T cost[], S res[], void *mem = wmem){ int i, j, k, r; S **dp; walloc2d(&dp, N, 1<::max(); rep(i,1,N) rep(j,1,1<=i, j+1, j]][if[k>=i, k+1, k]]; return graph_minColor(N-1, hv, mem) + if[mx==0, 0, 1]; } } logN = 1; while(N >> logN) logN++; walloc1d(&edge, N, &mem); rep(i,N) edge[i] = 0; rep(i,N) rep(j,N) if(i!=j && !mat[i][j]) edge[i] |= 1< T maxRectArea(int N, T H[], void *mem = wmem){ int i, sz = 0; T res, *st_h; int *st_w; if(N == 0) return 0; walloc1d(&st_h, N, &mem); walloc1d(&st_w, N, &mem); res = 0; rep(i,N){ if(sz == 0 || st_h[sz-1] <= H[i]){ st_h[sz] = H[i]; st_w[sz] = i; sz++; } else { while(sz && st_h[sz-1] > H[i]){ res >?= st_h[sz-1] * (i - st_w[sz-1]); sz--; } st_h[sz] = H[i]; sz++; } } while(sz){ res >?= st_h[sz-1] * (N - st_w[sz-1]); sz--; } return res; } template auto maxRectArea(int N, T H[], S W[], void *mem = wmem) -> decltype(H[0]*W[0]) { int i, sz = 0; decltype(H[0]*W[0]) res, ws, *st_h, *st_w; if(N == 0) return 0; walloc1d(&st_h, N, &mem); walloc1d(&st_w, N, &mem); res = ws = 0; rep(i,N){ if(sz == 0 || st_h[sz-1] <= H[i]){ st_h[sz] = H[i]; st_w[sz] = ws; sz++; } else { while(sz && st_h[sz-1] > H[i]){ res >?= st_h[sz-1] * (ws - st_w[sz-1]); sz--; } st_h[sz] = H[i]; sz++; } ws += W[i]; } while(sz){ res >?= st_h[sz-1] * (ws - st_w[sz-1]); sz--; } return res; } ------------------------------- isValidBracket1 ------ int isValidBracket1(int N, char S[]){ int i, k = 0; if(N%2) return 0; rep(i,N){ if(S[i] == '(') k++; else if(S[i] == ')') k--; else return 0; if(k < 0) return 0; } if(k==0) return 1; return 0; } ------------------------------- isValidBracket2 ------ int isValidBracket2(int N, char S[], void *mem = wmem){ int i, sz = 0; char *s; if(N%2) return 0; walloc1d(&s, N, &mem); rep(i,N){ if(S[i] == ')'){ if(sz == 0 || s[sz-1] != '(') return 0; sz--; continue; } if(S[i] == ']'){ if(sz == 0 || s[sz-1] != '[') return 0; sz--; continue; } if(S[i] == '}'){ if(sz == 0 || s[sz-1] != '{') return 0; sz--; continue; } if(S[i] == '>'){ if(sz == 0 || s[sz-1] != '<') return 0; sz--; continue; } s[sz++] = S[i]; } if(sz==0) return 1; return 0; } ------------------------------- swapV ------ template inline void swapV(T &a, T1 x, T2 y){ if(a == x) a = y; else if(a == y) a = x; } ------------------------------- cntSubarrayFreq ------ template ll cntSubarrayFreq(int N, T A[], S lim[], void *mem = wmem){ int i, j, *f; T mx, mn; ll res = 0; if(N == 0) return 0; rep(i,N) if(lim[A[i]] < 0) return 0; mn = mx = A[0]; rep(i,1,N){ mn ?= A[i]; } walloc1d(&f, mn, mx+1, &mem); rep(i,N) f[A[i]] = lim[A[i]]; i = 0; rep(j,N){ f[A[j]]--; while(f[A[j]] < 0){ f[A[i]]++; i++; } res += j - i + 1; } return res; } ------------------------------- cntSubarrayDistinct ------ template ll cntSubarrayDistinct(int N, T A[], S cost[], S2 lim, void *mem = wmem){ int i, j, *f; T mx, mn; S2 cur = 0; ll res = 0; if(N == 0 || lim < 0) return 0; mn = mx = A[0]; rep(i,1,N){ mn ?= A[i]; } walloc1d(&f, mn, mx+1, &mem); rep(i,N) f[A[i]] = 0; i = 0; rep(j,N){ if(f[A[j]] == 0) cur += cost[A[j]]; f[A[j]]++; while(cur > lim){ f[A[i]]--; if(f[A[i]] == 0) cur -= cost[A[i]]; i++; } res += j - i + 1; } return res; } ------------------------------- maxSubarrayDistinct ------ template int maxSubarrayDistinct(int N, T A[], S cost[], S2 lim, void *mem = wmem){ int i, j, *f; T mx, mn; S2 cur = 0; int res = 0; if(N == 0 || lim < 0) return 0; mn = mx = A[0]; rep(i,1,N){ mn ?= A[i]; } walloc1d(&f, mn, mx+1, &mem); rep(i,N) f[A[i]] = 0; i = 0; rep(j,N){ if(f[A[j]] == 0) cur += cost[A[j]]; f[A[j]]++; while(cur > lim){ f[A[i]]--; if(f[A[i]] == 0) cur -= cost[A[i]]; i++; } res >?= j - i + 1; } return res; } ------------------------------- vec2arr ------ template inline int vec2arr(vector &v, S arr[]){ int i, N = v.size(); rep(i,N) arr[i] = v[i]; return N; } template inline int vec2arr(vector> &v, S1 arr1[], S2 arr2[]){ int i, N = v.size(); rep(i,N){ arr1[i] = v[i][0]; arr2[i] = v[i][1]; } return N; } template inline int vec2arr(vector> &v, S1 arr1[], S2 arr2[], S3 arr3[]){ int i, N = v.size(); rep(i,N){ arr1[i] = v[i][0]; arr2[i] = v[i][1]; arr3[i] = v[i][2]; } return N; } ------------------------------- Rot90 ------ template vector> Rot90(vector> a){ int i, j, x, y; x = a.size(); y = a[0].size(); vector> b(y, vector(x)); rep(i,x) rep(j,y) b[j][x-1-i] = a[i][j]; return b; } ------------------------------- Point2dEPS ------ template struct Point2dEPS { static T eps; void set(T a){eps = a;} }; template T Point2dEPS::eps; void Point2d_init(void){ Point2dEPS x; x.set(1e-4); Point2dEPS y; y.set(1e-10); Point2dEPS z; z.set(1e-10); } ------------------------------- Point2dEPS_init ------ {Point2d_init();} ------------------------------- Point2d ------ template struct Point2d{ T x, y; Point2d(){x = y = 0;} Point2d(T a){x = a; y = 0;} Point2d(T a, T b){x = a; y = b;} void set(T a, T b){ x = a; y = b; } Point2d &operator+=(Point2d a){ x += a.x; y += a.y; return *this; } Point2d &operator-=(Point2d a){ x -= a.x; y -= a.y; return *this; } Point2d operator+(Point2d a){ return Point2d(*this)+=a; } Point2d operator-(Point2d a){ return Point2d(*this)-=a; } inline F dist(void){ F tx, ty; tx = x; ty = y; return sqrt(tx*tx + ty*ty); } inline F dist(Point2d a){ F tx, ty; tx = ((F)x) - ((F)a.x); ty = ((F)y) - ((F)a.y); return sqrt(tx*tx + ty*ty); } inline S dist2(void){ S tx, ty; tx = x; ty = y; return tx*tx + ty*ty; } inline S dist2(Point2d a){ S tx, ty; tx = ((S)x) - ((S)a.x); ty = ((S)y) - ((S)a.y); return tx*tx + ty*ty; } inline F arg(void){ F res; if(x==0 && y==0) return 0; res = atan2(y, x); if(res <= -PI + Point2dEPS::eps) res += 2*PI; return res; } inline F arg(Point2d a){ F res; res = arg() - a.arg(); if(res <= -PI + Point2dEPS::eps) res += 2*PI; if(res > PI + Point2dEPS::eps) res -= 2*PI; return res; } }; template inline Point2d operator*(T a, Point2d b){return Point2d(a*b.x, a*b.y);} ------------------------------- reader_Point2d ------ template void rd(Point2d &a){ reader_ignore_error(a.x, a.y); } ------------------------------- writer_Point2d ------ template void wt_L(Point2d a){ wt_L(a.x); wt_L(' '); wt_L(a.y); } ------------------------------- Point2d_InnerProd ------ template S InnerProd(Point2d a, Point2d b){ return ((S)a.x) * ((S)b.x) + ((S)a.y) * ((S)b.y); } ------------------------------- Point2d_CrossProd ------ template S CrossProd(Point2d a, Point2d b){ return ((S)a.x) * ((S)b.y) - ((S)b.x) * ((S)a.y); } template S CrossProd(Point2d c, Point2d a, Point2d b){ S x1, x2, y1, y2; x1 = ((S)a.x) - ((S)c.x); y1 = ((S)a.y) - ((S)c.y); x2 = ((S)b.x) - ((S)c.x); y2 = ((S)b.y) - ((S)c.y); return x1 * y2 - x2 * y1; } ------------------------------- Point2d_xysortA ------ template void xysortA(int N, Point2d A[]){ sort( A, A+N, [](auto &a, auto &b){ if(a.x < b.x - Point2dEPS::eps) return true; if(b.x < a.x - Point2dEPS::eps) return false; if(a.y < b.y - Point2dEPS::eps) return true; return false; } ); } template void xysortA(int N, Point2d A[], D ind[], void *mem = wmem){ int i; pair,D> *arr; arr = walloc1d(N,&arr,&mem); rep(i,N) arr[i] = make_pair(A[i],ind[i]); sort( arr, arr+N, [](auto &a, auto &b){ if(a.first.x < b.first.x - Point2dEPS::eps) return true; if(b.first.x < a.first.x - Point2dEPS::eps) return false; if(a.first.y < b.first.y - Point2dEPS::eps) return true; return false; } ); rep(i,N) A[i] = arr[i].first, ind[i] = arr[i].second; } ------------------------------- Point2d_argsortA ------ template void argsortA(int N, Point2d A[], void *mem = wmem){ int i, k, c, sz[4] = {}, *sp; Point2d *arr[4]; walloc1d(&sp, N, &mem); rep(i,N){ if(A[i].x >= -Point2dEPS::eps){ if(A[i].y >= -Point2dEPS::eps){ sp[i] = 2; } else { sp[i] = 1; } } else { if(A[i].y >= -Point2dEPS::eps){ sp[i] = 3; } else { sp[i] = 0; } } sz[sp[i]]++; } rep(k,4) walloc1d(&arr[k], sz[k], &mem); rep(k,4) sz[k] = 0; rep(i,N){ k = sp[i]; arr[k][sz[k]++] = A[i]; } rep(k,4) if(sz[k]){ sort( arr[k], arr[k]+sz[k], [](auto &a, auto &b){ return CrossProd(b, a) < -Point2dEPS::eps; } ); } c = 0; rep(k,4) rep(i,sz[k]) A[c++] = arr[k][i]; } template void argsortA(int N, Point2d A[], D ind[], void *mem = wmem){ int i, k, c, sz[4] = {}, *sp; pair,D> *arr[4]; walloc1d(&sp, N, &mem); rep(i,N){ if(A[i].x >= -Point2dEPS::eps){ if(A[i].y >= -Point2dEPS::eps){ sp[i] = 2; } else { sp[i] = 1; } } else { if(A[i].y >= -Point2dEPS::eps){ sp[i] = 3; } else { sp[i] = 0; } } sz[sp[i]]++; } rep(k,4) walloc1d(&arr[k], sz[k], &mem); rep(k,4) sz[k] = 0; rep(i,N){ k = sp[i]; arr[k][sz[k]++] = make_pair(A[i], ind[i]); } rep(k,4) if(sz[k]){ sort( arr[k], arr[k]+sz[k], [](auto &a, auto &b){ return CrossProd(b.first, a.first) < -Point2dEPS::eps; } ); } c = 0; rep(k,4) rep(i,sz[k]){ A[c] = arr[k][i].first; ind[c] = arr[k][i].second; c++; } } ------------------------------- Point2d_CCW ------ template int CCW(Point2d b, Point2d c){ S p; p = CrossProd(b, c); if(p < -Point2dEPS::eps) return -1; if(p > Point2dEPS::eps) return 1; p = InnerProd(b, c); if(p < -Point2dEPS::eps) return 2; p = c.dist2() - b.dist2(); if(p > Point2dEPS::eps) return -2; return 0; } template int CCW(Point2d a, Point2d b, Point2d c){ S p; b -= a; c -= a; p = CrossProd(b, c); if(p < -Point2dEPS::eps) return -1; if(p > Point2dEPS::eps) return 1; p = InnerProd(b, c); if(p < -Point2dEPS::eps) return 2; p = c.dist2() - b.dist2(); if(p > Point2dEPS::eps) return -2; return 0; } ------------------------------- Point2d_ConvexHull ------ template int ConvexHull_sorted(int N, Point2d A[], Point2d res[]){ int i, sz = 0, t; if(N <= 2){ rep(i,N) res[i] = A[i]; res[N] = A[0]; return N; } for(i=0; i= 2 && CCW(res[sz-2], res[sz-1], A[i]) <= 0) sz--; } t = sz; for(i=N-2; i>=0; res[sz++] = A[i--]){ while(sz > t && CCW(res[sz-2], res[sz-1], A[i]) <= 0) sz--; } return sz - 1; } template int ConvexHull(int N, Point2d A[], Point2d res[], void *mem = wmem){ int i; Point2d *arr; walloc1d(&arr, N, &mem); rep(i,N) arr[i] = A[i]; xysortA(N, arr); return ConvexHull_sorted(N, arr, res); } ------------------------------- Point2d_PolygonArea2 ------ template S PolygonArea2(int N, Point2d A[]){ int i; S res = 0; if(N <= 2) return res; rep(i,1,N) res += CrossProd(A[i-1], A[i]); res += CrossProd(A[N-1], A[0]); return res; } ------------------------------- minFactorList ------ template void minFactorList(int N, T res[]){ int i, j; if(N <= 2){ rep(i,N) res[i] = i; return; } res[0] = 0; res[1] = 1; for(i=2;i void maxFactorList(int N, T res[]){ int i, j; if(N <= 2){ rep(i,N) res[i] = i; return; } res[0] = 0; res[1] = 1; for(i=2;i void FactorList(int N, T res[], void *mem = wmem){ int i, j, k, *f; walloc1d(&f, N, &mem); maxFactorList(N, f); rep(i,N) res[i] = 0; rep(i,2,N){ k = i; while(k > 1){ j = f[k]; k /= j; while(f[k]==j) k /= j; res[i]++; } } } ------------------------------- FactorMList ------ template void FactorMList(int N, T res[], void *mem = wmem){ int i, k, *f; walloc1d(&f, N, &mem); maxFactorList(N, f); rep(i,N) res[i] = 0; rep(i,2,N){ k = i; while(k > 1){ k /= f[k]; res[i]++; } } } ------------------------------- EulerPhiList ------ template void EulerPhiList(int N, T res[], void *mem = wmem){ int i, j, k, *f; walloc1d(&f, N, &mem); maxFactorList(N, f); rep(i,N) res[i] = i; rep(i,2,N){ res[i] = i; k = i; while(k > 1){ j = f[k]; k /= j; while(f[k]==j) k /= j; res[i] = res[i] / j * (j-1); } } } ------------------------------- LinearEquationMod2 ------ template int LinearEquationMod2(int R, int C, T1 **A, T2 *b, void *mem = wmem){ const int LBIT = 64; const int bc = C / LBIT + 1; int i, j, r, c, bcs; ull **mat; walloc2d(&mat, R, bc, &mem); rep(i,R) rep(j,bc) mat[i][j] = 0; rep(i,R) rep(j,C) if(A[i][j]) mat[i][j/LBIT] |= (1ULL<<(j%LBIT)); rep(i,R) if(b[i]) mat[i][C/LBIT] |= (1ULL<<(C%LBIT)); r = 0; rep(c,C){ rep(i,r,R) if(mat[i][c/LBIT] & (1ULL << (c%LBIT))) break; if(i==R) continue; bcs = c / LBIT; if(i != r){ rep(j,bcs,bc) swap(mat[r][j], mat[i][j]); } rep(i,r+1,R) if(mat[i][c/LBIT] & (1ULL << (c%LBIT))){ rep(j,bcs,bc) mat[i][j] ^= mat[r][j]; } r++; } rep(i,r,R) if(mat[i][bc-1]) return -1; return C - r; } ------------------------------- LinearEquation ------ double LinearEquation_EPS = 1e-9; template int LinearEquation_for_real(int R, int C, T **A, T *b, T *x, void *mem = wmem){ int i, j, p, rr = 0, cc; T tmp, tmp2; T **aa, *bb; walloc2d(&aa, R, C, &mem); walloc1d(&bb, R, &mem); rep(i,R) rep(j,C) aa[i][j] = A[i][j]; rep(i,R) bb[i] = b[i]; rep(cc,C) if(rr < R){ tmp = -1; rep(p,rr,R){ tmp2 = abs(aa[p][cc]); if(tmp < tmp2) tmp = tmp2, i = p; } if(tmp < LinearEquation_EPS) continue; if(i != rr){ rep(j,cc,C) swap(aa[rr][j], aa[i][j]); swap(bb[rr], bb[i]); } rep(i,rr+1,R) if(aa[i][cc]){ tmp = aa[i][cc] / aa[rr][cc]; rep(j,cc,C) aa[i][j] -= tmp * aa[rr][j]; bb[i] -= tmp * bb[rr]; } rr++; } rep(i,rr,R) if(abs(bb[i]) >= LinearEquation_EPS) return -1; rep(i,C) x[i] = 0; rrep(i,rr){ rep(j,C) if(aa[i][j] >= LinearEquation_EPS) break; x[j] = bb[i]; rep(k,j+1,C) x[j] -= x[k] * aa[i][k]; x[j] /= aa[i][j]; } return C - rr; } template int LinearEquation_for_modint(int R, int C, T **A, T *b, T *x, void *mem = wmem){ int i, j, rr = 0, cc; T tmp; T **aa, *bb; walloc2d(&aa, R, C, &mem); walloc1d(&bb, R, &mem); rep(i,R) rep(j,C) aa[i][j] = A[i][j]; rep(i,R) bb[i] = b[i]; rep(cc,C) if(rr < R){ rep(i,rr,R) if(aa[i][cc]) break; if(i == R) continue; if(i != rr){ rep(j,cc,C) swap(aa[rr][j], aa[i][j]); swap(bb[rr], bb[i]); } rep(i,rr+1,R) if(aa[i][cc]){ tmp = aa[i][cc] / aa[rr][cc]; rep(j,cc,C) aa[i][j] -= tmp * aa[rr][j]; bb[i] -= tmp * bb[rr]; } rr++; } rep(i,rr,R) if(bb[i]) return -1; rep(i,C) x[i] = 0; rrep(i,rr){ rep(j,C) if(aa[i][j]) break; x[j] = bb[i]; rep(k,j+1,C) x[j] -= x[k] * aa[i][k]; x[j] /= aa[i][j]; } return C - rr; } template int LinearEquation(int R, int C, T **A, T *b, T *x, void *mem = wmem){ return LinearEquation_for_real(R, C, A, b, x, mem); } ------------------------------- LinearEquation_Modint ------ int LinearEquation(int R, int C, Modint **A, Modint *b, Modint *x, void *mem = wmem){ return LinearEquation_for_modint(R, C, A, b, x, mem); } ------------------------------- LinearEquation_Mint ------ int LinearEquation(int R, int C, Mint **A, Mint *b, Mint *x, void *mem = wmem){ return LinearEquation_for_modint(R, C, A, b, x, mem); } ------------------------------- LinearEquation_modint ------ int LinearEquation(int R, int C, modint **A, modint *b, modint *x, void *mem = wmem){ return LinearEquation_for_modint(R, C, A, b, x, mem); } ------------------------------- LinearEquation_mint ------ int LinearEquation(int R, int C, mint **A, mint *b, mint *x, void *mem = wmem){ return LinearEquation_for_modint(R, C, A, b, x, mem); } ------------------------------- LexicographicGE ------ template int LexicographicGE(int N, T1 A[], int sz, T2 available_num[], T3 res[], void *mem = wmem){ int i, k, *nx; T1 *av; walloc1d(&av, sz, &mem); rep(i,sz) av[i] = available_num[i]; rep(i,1,sz) if(av[i-1] > av[i]){ sort(av, av+sz); break; } walloc1d(&nx, N, &mem); rep(i,N){ nx[i] = lower_bound(av, av+sz, A[i]) - av; if(nx[i] == sz){ while(i >= 0 && nx[i] >= sz-1) i--; if(i < 0){ rep(k,N) res[k] = av[0]; return 0; } rep(k,i) res[k] = A[k]; res[i] = av[nx[i]+1]; rep(k,i+1,N) res[k] = av[0]; return 1; } if(A[i] != av[nx[i]]){ rep(k,i) res[k] = A[k]; res[i] = av[nx[i]]; rep(k,i+1,N) res[k] = av[0]; return 1; } } rep(i,N) res[i] = A[i]; return 1; } ------------------------------- cReader_ll ------ ll cReader_ll(ll mn, ll mx, char nx){ int i, fg = 0, m = 1, f = -1; ll res = 0; double tmp = 0; for(;;){ i = my_getchar_unlocked(); if(fg==0 && i=='-'){ fg++; m = -1; } else if('0' <= i <= '9'){ fg++; if(f == -1) f = i - '0'; res = 10 * res + i - '0'; tmp = 10 * tmp + i - '0'; assert(tmp < 1e20); } else { break; } } assert(tmp / 2 <= res); assert((m==1 && fg >= 1) || (m==-1 && fg >= 2)); assert(mn <= m * res <= mx); assert(!(res == 0 && m == -1)); assert(!(res != 0 && f == 0)); assert(!(res == 0 && fg >= 2)); assert(i == nx); return m * res; } ------------------------------- cReader_eof ------ void cReader_eof(){ int i; i = my_getchar_unlocked(); assert(i == EOF); } ------------------------------- cntPrime ------ ll cntPrime(ll n, void *mem = wmem){ int i, j, k, m, sn, ssn, c; char *isp; ll *s1, *s2, x, tmp; const double nn = n; if(n <= 1) return 0; if(n == 2) return 1; c = 0; sn = Isqrt_f(n); ssn = Isqrt_f(sn); walloc1d(&s1, sn+1, &mem); walloc1d(&s2, sn+1, &mem); walloc1d(&isp, sn+1, &mem); s1[0] = 0; rep(i,1,sn+1) s1[i] = i - 1; rep(i,1,sn+1) s2[i] = n/i - 1; rep(i,2,sn+1) isp[i] = 1; rep(i,2,ssn+1) if(isp[i]){ for(j=i*i;j<=sn;j+=i) isp[j] = 0; rep(j,1,sn+1){ x = (ll) i * j; if(x > sn) s2[j] -= s1[(int)(nn / x)] - c; else s2[j] -= s2[x] - c; } for(k = (sn+1)/i; k >= i; k--){ m = min(sn+1, i*(k+1)); tmp = s1[k] - c; rep(j,i*k,m) s1[j] -= tmp; } c++; } rep(i,ssn+1,sn+1) if(isp[i]){ rep(j,1,sn+1){ x = (ll) i * j; if(x * i > n) break; if(x > sn) s2[j] -= s1[(int)(nn / x)] - c; else s2[j] -= s2[x] - c; } c++; } return s2[1]; } ------------------------------- sumPrime ------ template T sumPrime(ll n, void *mem = wmem){ int i, j, k, m, sn, ssn; char *isp; ll x; T *s1, *s2, c, tmp; const double nn = n; if(n <= 1) return 0; if(n == 2) return 2; c = 0; sn = Isqrt_f(n); ssn = Isqrt_f(sn); walloc1d(&s1, sn+1, &mem); walloc1d(&s2, sn+1, &mem); walloc1d(&isp, sn+1, &mem); s1[0] = 0; rep(i,1,sn+1) s1[i] = ((T)i) * ((T)(i+1)) / 2 - 1; rep(i,1,sn+1) s2[i] = ((T)(n/i)) * ((T)(n/i+1)) / 2 - 1; rep(i,2,sn+1) isp[i] = 1; rep(i,2,ssn+1) if(isp[i]){ for(j=i*i;j<=sn;j+=i) isp[j] = 0; rep(j,1,sn+1){ x = (ll) i * j; if(x > sn) s2[j] -= i * (s1[(int)(nn / x)] - c); else s2[j] -= i * (s2[x] - c); } for(k = (sn+1)/i; k >= i; k--){ m = min(sn+1, i*(k+1)); tmp = i * (s1[k] - c); rep(j,i*k,m) s1[j] -= tmp; } c += i; } rep(i,ssn+1,sn+1) if(isp[i]){ rep(j,1,sn+1){ x = (ll) i * j; if(x * i > n) break; if(x > sn) s2[j] -= i * (s1[(int)(nn / x)] - c); else s2[j] -= i * (s2[x] - c); } c += i; } return s2[1]; } ------------------------------- Determinant_Modint ------ Modint Determinant(int n, Modint **mat, void *mem = wmem){ int i, j, c; Modint **m; Modint res = 1, tmp; walloc2d(&m, n, n, &mem); rep(i,n) rep(j,n) m[i][j] = mat[i][j]; rep(c,n){ rep(i,c,n) if(m[i][c]) break; if(i==n) return 0; if(i!=c){ rep(j,c,n) swap(m[i][j], m[c][j]); res = -res; } rep(i,c+1,n) if(m[i][c]){ tmp = m[i][c] / m[c][c]; rep(j,c+1,n) m[i][j] -= tmp * m[c][j]; } res *= m[c][c]; } return res; } ------------------------------- Determinant_modint ------ modint Determinant(int n, modint **mat, void *mem = wmem){ int i, j, c; modint **m; modint res = 1, tmp; walloc2d(&m, n, n, &mem); rep(i,n) rep(j,n) m[i][j] = mat[i][j]; rep(c,n){ rep(i,c,n) if(m[i][c]) break; if(i==n) return 0; if(i!=c){ rep(j,c,n) swap(m[i][j], m[c][j]); res = -res; } rep(i,c+1,n) if(m[i][c]){ tmp = m[i][c] / m[c][c]; rep(j,c+1,n) m[i][j] -= tmp * m[c][j]; } res *= m[c][c]; } return res; } ------------------------------- Determinant_Mint ------ Mint Determinant(int n, Mint **mat, void *mem = wmem){ int i, j, c; Mint **m; Mint res = 1, tmp; walloc2d(&m, n, n, &mem); rep(i,n) rep(j,n) m[i][j] = mat[i][j]; rep(c,n){ rep(i,c,n) if(m[i][c]) break; if(i==n) return 0; if(i!=c){ rep(j,c,n) swap(m[i][j], m[c][j]); res = -res; } rep(i,c+1,n) if(m[i][c]){ tmp = m[i][c] / m[c][c]; rep(j,c+1,n) m[i][j] -= tmp * m[c][j]; } res *= m[c][c]; } return res; } ------------------------------- Determinant_mint ------ mint Determinant(int n, mint **mat, void *mem = wmem){ int i, j, c; mint **m; mint res = 1, tmp; walloc2d(&m, n, n, &mem); rep(i,n) rep(j,n) m[i][j] = mat[i][j]; rep(c,n){ rep(i,c,n) if(m[i][c]) break; if(i==n) return 0; if(i!=c){ rep(j,c,n) swap(m[i][j], m[c][j]); res = -res; } rep(i,c+1,n) if(m[i][c]){ tmp = m[i][c] / m[c][c]; rep(j,c+1,n) m[i][j] -= tmp * m[c][j]; } res *= m[c][c]; } return res; } ------------------------------- arrMerge ------ template int arrMerge(int As, T1 A[], int Bs, T2 B[], T3 res[]){ int aa = 0, bb = 0, sz = 0; while(aa < As && bb < Bs){ if(A[aa] <= B[bb]){ res[sz++] = A[aa++]; } else { res[sz++] = B[bb++]; } } while(aa < As) res[sz++] = A[aa++]; while(bb < Bs) res[sz++] = B[bb++]; return sz; } ------------------------------- arrMergeD ------ template int arrMergeD(int As, T1 A[], int Bs, T2 B[], T3 res[]){ int aa = 0, bb = 0, sz = 0; while(aa < As && bb < Bs){ if(A[aa] == B[bb]){ res[sz++] = A[aa++]; bb++; } else if(A[aa] <= B[bb]){ res[sz++] = A[aa++]; } else { res[sz++] = B[bb++]; } } while(aa < As) res[sz++] = A[aa++]; while(bb < Bs) res[sz++] = B[bb++]; return sz; } ------------------------------- opt01SubsetSum_brute ------ template T opt01SubsetSum_brute(int N, T A[], T t, T notfound = -1){ T res, tmp; int ok = 0, mask, i; rep(mask,1< T opt01SubsetSum_mim(int N, T A[], T t, T notfound = -1, void *mem = wmem){ int i, j, n1, n2, s1, s2; T *a, *a1, *a2, res, sm, ad; walloc1d(&a, N, &mem); rep(i,N) a[i] = A[i]; ad = 0; rep(i,N) if(a[i] < 0) a[i] = -a[i], ad += a[i]; t += ad; if(t < 0) return notfound; sort(a, a+N); while(N && a[N-1] > t) N--; if(N==0){ if(t >= 0) return -ad; return notfound; } sm = 0; rep(i,N){ if(a[i] > 0) sm += a[i]; if(sm == t) return t - ad; } if(sm < t) return sm - ad; n1 = N / 2; n2 = N - n1; walloc1d(&a1, 1<= 0 && a1[i] + a2[j] > t) j--; if(j < 0) break; res >?= a1[i] + a2[j]; } return res - ad; } ------------------------------- opt01SubsetSum_sdp ------ template T opt01SubsetSum_sdp(int N, T A[], T t, T notfound = -1, void *mem = wmem){ int i, k; T *a, sm, ad, g; char *arr; walloc1d(&a, N, &mem); rep(i,N) a[i] = A[i]; ad = 0; rep(i,N) if(a[i] < 0) a[i] = -a[i], ad += a[i]; t += ad; if(t < 0) return notfound; sort(a, a+N); while(N && a[N-1] > t) N--; if(N==0){ if(t >= 0) return -ad; return notfound; } walloc1d(&arr, t+1, &mem); while(N > 0 && a[N-1] > t) N--; sm = 0; rep(i,N){ sm += a[i]; if(sm == t) return t - ad; } if(sm < t) return sm - ad; g = a[0]; rep(i,1,N) g = gcd(g, a[i]); if(g > 1){ rep(i,N) a[i] /= g; t = fDiv(t, g); } arr[0] = 1; rep(i,1,t+1) arr[i] = 0; sm = 0; rep(k,N){ sm = min(sm + a[k], t); rrep(i,a[k],sm+1) arr[i] |= arr[i-a[k]]; } rrep(i,t+1) if(arr[i]) return i*g - ad; return notfound; } ------------------------------- opt01SubsetSum ------ template T opt01SubsetSum(int N, T A[], T t, T notfound = -1, int mem_lim = sizeof(memarr)/2, void *mem = wmem){ int i; T g; double x; double min_time; double time_brute, time_mim, time_sdp; double memo_brute, memo_mim, memo_sdp; min_time = double_inf; time_brute = pow(2.0, N) * N; memo_brute = 1; if(memo_brute > mem_lim) time_brute = double_inf; min_time mem_lim) time_mim = double_inf; min_time 1) time_sdp /= g; memo_sdp = time_sdp * sizeof(T); if(memo_sdp > mem_lim) time_sdp = double_inf; min_time T opt01SubsetSumF_brute(int N, int F, T A[], T t, T notfound = -1){ T res, tmp; int ind[N]; int ok = 0, mask, i; if(F < 0 || F > N) return notfound; rep(i,N) ind[i] = 0; rep(i,F) ind[N-1-i] = 1; do{ tmp = 0; rep(i,N) if(ind[i]) tmp += A[i]; if(tmp <= t){ if(!ok) ok = 1, res = tmp; else if(res < tmp) res = tmp; } }while(next_permutation(ind,ind+N)); if(!ok) return notfound; return res; } ------------------------------- opt01SubsetSumF_mim ------ template T opt01SubsetSumF_mim(int N, int F, T A[], T t, T notfound = -1, void *mem = wmem){ int i, j, k, n1, n2, nn, *s1, *s2, *mis; T *a, **a1, **a2, res, sm, ad, x, y; T *arr1, *arr2; int arrsz1, arrsz2, st1, st2; ll **c; if(F < 0 || F > N) return notfound; walloc1d(&a, N, &mem); walloc1d(&mis, N, &mem); rep(i,N) a[i] = A[i]; sort(a, a+N); sm = 0; rep(i,F) sm += a[i]; if(sm > t) return notfound; sm = 0; rep(i,F) sm += a[N-1-i]; if(sm <= t) return sm; rep(i,N) a[i] = A[i]; rep(i,N) mis[i] = 0; ad = 0; rep(i,N) if(a[i] < 0){ a[i] = -a[i]; ad += a[i]; mis[i] = 1; } t += ad; if(t < 0) return notfound; sortA(N, a, mis, mem); while(N && a[N-1] > t){ F -= mis[N-1]; N--; } n1 = N / 2; n2 = N - n1; nn = max(n1, n2); walloc2d(&c, nn+1, nn+1, &mem); rep(i,nn+1) c[i][0] = 1; rep(j,1,nn+1) c[0][j] = 0; rep(i,1,nn+1) rep(j,1,nn+1) c[i][j] = c[i-1][j-1] + c[i-1][j]; walloc1d(&s1, n1+1, &mem); walloc1d(&a1, n1+1, &mem); rep(i,n1+1) walloc1d(&a1[i], c[n1][i], &mem); walloc1d(&s2, n2+1, &mem); walloc1d(&a2, n2+1, &mem); rep(i,n2+1) walloc1d(&a2[i], c[n2][i], &mem); k = c[nn][nn/2]; walloc1d(&arr1, k, &mem); walloc1d(&arr2, k, &mem); x = 0; rep(i,n1) x += mis[i]; y = x; rep(i,n1+1) s1[i] = 0; a1[x][s1[x]++] = 0; rep(k,n1){ if(mis[k]==0){ rrep(j,x,y+1){ arrsz1 = s1[j]; arrsz2 = s1[j+1]; rep(i,arrsz1) arr1[i] = a1[j][i] + a[k]; rep(i,arrsz2) arr2[i] = a1[j+1][i]; s1[j+1] = arrMergeD(arrsz1, arr1, arrsz2, arr2, a1[j+1]); } y++; } else { rep(j,x,y+1){ arrsz1 = s1[j]; arrsz2 = s1[j-1]; rep(i,arrsz1) arr1[i] = a1[j][i] + a[k]; rep(i,arrsz2) arr2[i] = a1[j-1][i]; s1[j-1] = arrMergeD(arrsz1, arr1, arrsz2, arr2, a1[j-1]); } x--; } } x = 0; rep(i,n2) x += mis[n1+i]; y = x; rep(i,n2+1) s2[i] = 0; a2[x][s2[x]++] = 0; rep(k,n2){ if(mis[n1+k]==0){ rrep(j,x,y+1){ arrsz1 = s2[j]; arrsz2 = s2[j+1]; rep(i,arrsz1) arr1[i] = a2[j][i] + a[n1+k]; rep(i,arrsz2) arr2[i] = a2[j+1][i]; s2[j+1] = arrMergeD(arrsz1, arr1, arrsz2, arr2, a2[j+1]); } y++; } else { rep(j,x,y+1){ arrsz1 = s2[j]; arrsz2 = s2[j-1]; rep(i,arrsz1) arr1[i] = a2[j][i] + a[n1+k]; rep(i,arrsz2) arr2[i] = a2[j-1][i]; s2[j-1] = arrMergeD(arrsz1, arr1, arrsz2, arr2, a2[j-1]); } x--; } } res = -int_inf; rep(st1,n1+1){ st2 = F - st1; if(st2 < 0 || st2 > n2) continue; j = s2[st2] - 1; rep(i,s1[st1]){ while(j >= 0 && a1[st1][i] + a2[st2][j] > t) j--; if(j < 0) break; res >?= a1[st1][i] + a2[st2][j]; } } return res - ad; } ------------------------------- opt01SubsetSumF_sdp ------ template T opt01SubsetSumF_sdp(int N, int F, T A[], T t, T notfound = -1, void *mem = wmem){ int i, j, k, x, y, *mis; T *a, sm, ad, *mx, g; char **arr; if(F < 0 || F > N) return notfound; walloc1d(&a, N, &mem); walloc1d(&mis, N, &mem); rep(i,N) a[i] = A[i]; sort(a, a+N); sm = 0; rep(i,F) sm += a[i]; if(sm > t) return notfound; sm = 0; rep(i,F) sm += a[N-1-i]; if(sm <= t) return sm; rep(i,N) a[i] = A[i]; rep(i,N) mis[i] = 0; ad = 0; rep(i,N) if(a[i] < 0){ a[i] = -a[i]; ad += a[i]; mis[i] = 1; } t += ad; if(t < 0) return notfound; sortA(N, a, mis, mem); while(N && a[N-1] > t){ F -= mis[N-1]; N--; } g = 0; rep(i,N) g = gcd(g, a[i]); if(g > 1){ rep(i,N) a[i] /= g; t = fDiv(t, g); } walloc2d(&arr, N+1, t+1, &mem); walloc1d(&mx, N+1, &mem); x = 0; rep(i,N) x += mis[i]; y = x; rep(j,N+1) rep(i,t+1) arr[j][i] = 0; rep(j,N+1) mx[j] = -1; arr[x][0] = 1; mx[x] = 0; rep(k,N){ if(mis[k]==0){ rrep(j,x,y+1){ mx[j+1] = min(max(mx[j+1], mx[j] + a[k]), t); rep(i,a[k],mx[j+1]+1) arr[j+1][i] |= arr[j][i-a[k]]; } y++; } else { rep(j,x,y+1){ mx[j-1] = min(max(mx[j-1], mx[j] + a[k]), t); rep(i,a[k],mx[j-1]+1) arr[j-1][i] |= arr[j][i-a[k]]; } x--; } } rrep(i,t+1) if(arr[F][i]) return i*g - ad; return notfound; } ------------------------------- opt01SubsetSumF ------ template T opt01SubsetSumF(int N, int F, T A[], T t, T notfound = -1, int mem_lim = sizeof(memarr)/2, void *mem = wmem){ int i, k; T g; double x; double min_time; double time_brute, time_mim, time_sdp; double memo_brute, memo_mim, memo_sdp; if(F < 0 || F > N) return notfound; min_time = double_inf; time_brute = N; k = min(F, N-F); rep(i,k) time_brute = time_brute * (N-i) / (i+1); memo_brute = N * sizeof(int); if(memo_brute > mem_lim) time_brute = double_inf; min_time mem_lim) time_mim = double_inf; min_time 1) time_sdp /= g; memo_sdp = time_sdp * sizeof(T); if(memo_sdp > mem_lim) time_sdp = double_inf; min_time void cntArrayNecessaryElement(int N, int K, T **res){ int i, j; rep(i,N+1) rep(j,K+1) res[i][j] = 0; res[0][0] = 1; rep(i,N) rep(j,K+1){ if(j < K) res[i+1][j] += (K - j) * res[i][j]; if(j > 0) res[i+1][j] += j * res[i][j-1]; } } template void cntArrayNecessaryElement(int N, int K, T **res, T **cnt1, T **cnt2, void *mem = wmem){ int i, j; T *inv; walloc1d(&inv, K+1, &mem); rep(i,1,K+1) inv[i] = T(1) / T(i); rep(i,N+1) rep(j,K+1) res[i][j] = 0; rep(i,N+1) rep(j,K+1) cnt1[i][j] = 0; rep(i,N+1) rep(j,K+1) cnt2[i][j] = 0; res[0][0] = 1; rep(i,N) rep(j,K+1){ if(j < K){ res[i+1][j] += (K - j) * res[i][j]; cnt1[i+1][j] += (K - j) * cnt1[i][j]; } if(j > 0){ res[i+1][j] += j * res[i][j-1]; cnt1[i+1][j] += j * (cnt1[i][j-1] + res[i][j-1] + cnt2[i][j-1] * inv[K+1-j]); } cnt2[i+1][j] = res[i+1][j] * (i+1) - cnt1[i+1][j]; } rep(i,N) rep(j,1,K+1) cnt1[i+1][j] *= inv[j]; rep(i,N) rep(j,K) cnt2[i+1][j] *= inv[K-j]; } ------------------------------- cntArrayNecessaryElement_walloc ------ template void cntArrayNecessaryElement_walloc(int N, int K, T ***res, void **mem = &wmem){ walloc2d(res, N+1, K+1, mem); cntArrayNecessaryElement(N, K, *res); } template void cntArrayNecessaryElement_walloc(int N, int K, T ***res, T ***cnt1, T ***cnt2, void **mem = &wmem){ walloc2d(res, N+1, K+1, mem); walloc2d(cnt1, N+1, K+1, mem); walloc2d(cnt2, N+1, K+1, mem); cntArrayNecessaryElement(N, K, *res, *cnt1, *cnt2, *mem); } ------------------------------- arr2bit_int ------ template int arr2bit_int(const int N, const T A[], const T base = 0){ int i, res = 0; rep(i,N) res |= (1 << (A[i] - base)); return res; } int arr2bit_int(const string S, const char base = 0){ int i, res = 0; rep(i,(int)S.size()) res |= (1 << (S[i] - base)); return res; } ------------------------------- arr2bit_ll ------ template ll arr2bit_ll(const int N, const T A[], const T base = 0){ int i; ll res = 0; rep(i,N) res |= (1LL << (A[i] - base)); return res; } ll arr2bit_ll(const string S, const char base = 0){ int i; ll res = 0; rep(i,(int)S.size()) res |= (1LL << (S[i] - base)); return res; } ------------------------------- toLower ------ string toLower(const string S){ int i; string res = S; rep(i,res.size()) res[i] = tolower(res[i]); return res; } string toUpper(const string S){ int i; string res = S; rep(i,res.size()) res[i] = toupper(res[i]); return res; } ------------------------------- isSorted ------ template int isSorted(int N, const T A[]){ int i; rep(i,1,N) if(A[i-1] > A[i]) return 0; return 1; } ------------------------------- Slice ------ template int Slice(const int N, const T A[], const ll bg, const ll ed, const ll step, S res[]){ ll i, k, s; int len = 0; if(N == 0) return 0; s = step %% N; assert(step != 0); if(step > 0){ for(i = bg, k = bg %% N; i < ed; i += step, k += s){ if(k >= N) k -= N; res[len++] = A[k]; } } else { for(i = bg, k = bg %% N; i > ed; i += step, k += s){ if(k >= N) k -= N; res[len++] = A[k]; } } return len; } template vector Slice(const vector &A, const ll bg, const ll ed, const ll step){ const int N = A.size(); ll i, k, s; vector res; if(N == 0) return res; s = step %% N; assert(step != 0); if(step > 0){ for(i = bg, k = bg %% N; i < ed; i += step, k += s){ if(k >= N) k -= N; res.push_back(A[k]); } } else { for(i = bg, k = bg %% N; i > ed; i += step, k += s){ if(k >= N) k -= N; res.push_back(A[k]); } } return res; } string Slice(const string &A, const ll bg, const ll ed, const ll step){ const int N = A.size(); ll i, k, s; string res; if(N == 0) return res; s = step %% N; assert(step != 0); if(step > 0){ for(i = bg, k = bg %% N; i < ed; i += step, k += s){ if(k >= N) k -= N; res += A[k]; } } else { for(i = bg, k = bg %% N; i > ed; i += step, k += s){ if(k >= N) k -= N; res += A[k]; } } return res; } ------------------------------- RoundUp ------ template inline T RoundUp(T a, S b){ T m; if(b < 0) b = -b; if(b <= 1) return a; m = a % b; if(m == 0) return a; if(m < 0) m += b; return ((a + b - m) / b) * b; } ------------------------------- RoundDown ------ template inline T RoundDown(T a, S b){ T m; if(b < 0) b = -b; if(b <= 1) return a; m = a % b; if(m == 0) return a; if(m < 0) m += b; return ((a - m) / b) * b; } ------------------------------- startWith ------ template int startWith(const int As, const T1 A[], const int Bs, const T2 B[]){ int i; if(As < Bs) return 0; rep(i,Bs) if(A[i] != B[i]) return 0; return 1; } template int startWith(const vector &A, const vector &B){ int i; if(A.size() < B.size()) return 0; rep(i,B.size()) if(A[i] != B[i]) return 0; return 1; } int startWith(const string &A, const string &B){ int i; if(A.size() < B.size()) return 0; rep(i,B.size()) if(A[i] != B[i]) return 0; return 1; } ------------------------------- endWith ------ template int endWith(const int As, const T1 A[], const int Bs, const T2 B[]){ int i; if(As < Bs) return 0; const int k = As - Bs; rep(i,Bs) if(A[k+i] != B[i]) return 0; return 1; } template int endWith(const vector &A, const vector &B){ int i; if(A.size() < B.size()) return 0; const int k = A.size() - B.size(); rep(i,B.size()) if(A[k+i] != B[i]) return 0; return 1; } int endWith(const string &A, const string &B){ int i; if(A.size() < B.size()) return 0; const int k = A.size() - B.size(); rep(i,B.size()) if(A[k+i] != B[i]) return 0; return 1; } ------------------------------- MergeTech ------ template void MergeTech(set &A, set &B){ if(A.size() < B.size()) swap(A,B); for(auto x : B) A.insert(x); B.clear(); } template void MergeTech(multiset &A, multiset &B){ if(A.size() < B.size()) swap(A,B); for(auto x : B) A.insert(x); B.clear(); } template void MergeTech(vector &A, vector &B){ if(A.size() < B.size()) swap(A,B); for(auto x : B) A.push_back(x); B.clear(); } ------------------------------- WildEQ ------ int WildEQ(const string &A, const string &B, const char wc){ if(A.size() != B.size()) return 0; const int N = A.size(); for(int i = 0; i < N; i++){ if(A[i] != wc && B[i] != wc && A[i] != B[i]) return 0; } return 1; }