Last active
May 7, 2022 10:07
-
-
Save bhi5hmaraj/b36b14411c6a41d640257818dbdf2edf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*** | |
* | |
* This is my personal collections of redundant code snippets used in various programming problems | |
* | |
* @author Bhishmaraj S (matib275@gmail.com) | |
* */ | |
import java.util.*; | |
import java.util.stream.IntStream; | |
import java.io.*; | |
class Helper { | |
static int loPrime[]; | |
static int primes[]; | |
static BitSet segmentedSieve(long L , long R) { // Dependency primes array contains primes till sqrt(R) | |
int len = (int) (R - L + 1); | |
BitSet bitSet = new BitSet(len); | |
bitSet.set(0, len); | |
for(long p : primes) | |
for(long i = L % p == 0 ? L : L + (p - (L % p));i <= R;i += p) | |
if(i != p) | |
bitSet.set((int) (i - L) , false); | |
if(L == 1) | |
bitSet.set(0, false); | |
return bitSet; | |
} | |
static void loPrimeSieve(int N) // stores lowest prime factor of each number | |
// , used for calculating phi | |
{ | |
loPrime = new int[N + 1]; | |
int pr[] = new int[N]; | |
int sz = 0; | |
for (int i = 2; i <= N; ++i) { | |
if (loPrime[i] == 0) { | |
loPrime[i] = i; | |
pr[sz] = i; | |
sz++; | |
} | |
for (int j = 0; j < sz && pr[j] <= loPrime[i] && i * pr[j] <= N; ++j) | |
loPrime[i * pr[j]] = pr[j]; | |
} | |
} | |
static int lp[]; | |
static int fi[]; // euler totient function | |
static void fastFiSieve(int N) { | |
lp = new int[N + 1]; | |
fi = new int[N + 1]; | |
int pr[] = new int[N]; | |
int sz = 0; | |
fi[1] = 1; | |
for (int i = 2; i <= N; ++i) { | |
if (lp[i] == 0) { | |
lp[i] = i; | |
fi[i] = i - 1; | |
pr[sz] = i; | |
sz++; | |
} else { | |
// Calculating phi | |
if (lp[i] == lp[i / lp[i]]) | |
fi[i] = fi[i / lp[i]] * lp[i]; | |
else | |
fi[i] = fi[i / lp[i]] * (lp[i] - 1); | |
} | |
for (int j = 0; j < sz && pr[j] <= lp[i] && i * pr[j] <= N; ++j) | |
lp[i * pr[j]] = pr[j]; | |
} | |
} | |
static int bigPrime[]; | |
static int N; | |
private static void preCalBigPrimeSieve() // instead of the loPrimesieve you | |
// could use bigprimeSieve which | |
// has the same performance and | |
// its a lot more intutive | |
{ | |
bigPrime[1] = 1; | |
for (int i = 2; i <= N; i++) { | |
if (bigPrime[i] == 0) { | |
bigPrime[i] = i; | |
for (int j = 2 * i; j <= N; j += i) | |
bigPrime[j] = i; | |
} | |
} | |
} | |
static HashMap<Integer, Integer> primeFactorize(int N) // Dependency : A | |
// sieve (loPrime[]) | |
// which contains the | |
// lowest prime | |
// divisor for each | |
// number | |
{ | |
HashMap<Integer, Integer> mp = new HashMap<>(); | |
int ct, prime; | |
while (N != 1) { | |
prime = loPrime[N]; | |
ct = 0; | |
while (N % prime == 0) { | |
N /= prime; | |
ct++; | |
} | |
mp.put(prime, ct); | |
} | |
return mp; | |
} | |
private static long modPow(long a, long b) // squared exponentiation | |
{ | |
if (b == 0L || a == 1L) | |
return 1L; | |
else if (b == 1L) | |
return a; | |
else { | |
if ((b & 1L) == 0L) // Checking whether b is even (fast) | |
return modPow((a * a) % mod, b >> 1); | |
else | |
return (a * modPow((a * a) % mod, b >> 1)) % mod; | |
} | |
} | |
/*** | |
* Documentation for lower_bound() | |
* | |
* if the array = [2,4,6,7,10,12] 1. key = 1 return = -1 (u can insert to | |
* the left of this one based point) 2. key = 2 return = 0 3. key = 12 | |
* return = -6 4. key = 20 return = -7 | |
* | |
*/ | |
private static int lower_bound(int arr[], int key) // if it exists then | |
// returns the lower | |
// bound or else returns | |
// -(pos+1) | |
{ | |
int lo = 0; | |
int hi = arr.length - 1; | |
int mid = 0; | |
int pos = -1; | |
boolean flag = false; | |
while (lo <= hi) { | |
mid = (lo + hi) / 2; | |
if (arr[mid] >= key) { | |
if (arr[mid] == key && !flag) | |
flag = true; | |
hi = mid - 1; | |
pos = mid; | |
} else | |
lo = mid + 1; | |
} | |
if (flag) | |
return pos; | |
else { | |
if (pos == -1) | |
pos = arr.length; | |
pos = -(pos + 1); | |
return pos; | |
} | |
} | |
/* | |
* Hack: copy - a double[] , copy of int array upper_bound =( - ( | |
* Arrays.binarySearch(copy, (double)key + 0.5) + 1 ) ) lower_bound =( - ( | |
* Arrays.binarySearch(copy, (double)key - 0.5) + 1 ) ) | |
*/ | |
private static String[] substrings(String in) { | |
int len = in.length(); | |
String sub[] = new String[((len) * (len + 1)) / 2]; | |
int ptr = 0; | |
for (int i = 0; i < len; i++) | |
for (int j = i; j < len; j++) | |
sub[ptr++] = in.substring(j - i, j + 1); | |
return sub; | |
} | |
private static int log(long n, long b) { | |
if (n < 1L || b <= 1L) | |
throw new IllegalArgumentException("Wrong base or n"); | |
else { | |
int ct = 1; | |
while (n > 0) { | |
n /= b; | |
ct++; | |
} | |
return ct - 1; | |
} | |
} | |
private static void swap(char ch[], int j, int k) { | |
char temp = ch[j]; | |
ch[j] = ch[k]; | |
ch[k] = temp; | |
} | |
private static String nextBiggestPermutationModified(String str) // If it | |
// returns | |
// null | |
// then no | |
// permutation | |
// exists | |
{ | |
char ch[] = str.toCharArray(); | |
int i = ch.length - 1; | |
while (i > 0 && ch[i] <= ch[i - 1]) { | |
i--; | |
} | |
if (i != 0) { | |
for (int j = i, k = ch.length - 1; j <= (i + ch.length - 1) / 2; j++, k--) | |
swap(ch, j, k); | |
char start = ch[i - 1]; | |
int pos = i; | |
for (; pos < ch.length; pos++) | |
if (ch[pos] > start) | |
break; | |
swap(ch, pos, i - 1); | |
return new String(ch); | |
} else | |
return null; | |
} | |
private static int partition(int[] a, int lo, int hi) { | |
int i = lo; | |
int j = hi + 1; | |
int v = a[lo]; | |
while (true) { | |
// find item on lo to swap | |
while (less(a[++i], v)) | |
if (i == hi) | |
break; | |
// find item on hi to swap | |
while (less(v, a[--j])) | |
if (j == lo) | |
break; // redundant since a[lo] acts as sentinel | |
// if pointers cross | |
if (i >= j) | |
break; | |
exch(a, i, j); | |
} | |
// put partitioning item v at a[j] | |
exch(a, lo, j); | |
// now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi] | |
return j; | |
} | |
private static boolean less(int v, int w) { | |
return v - w < 0; | |
} | |
private static void exch(int[] a, int i, int j) { | |
int swap = a[i]; | |
a[i] = a[j]; | |
a[j] = swap; | |
} | |
private static int selection(int arr[], int k) { | |
int lo = 0, hi = arr.length - 1; | |
int pos = partition(arr, lo, hi); | |
while (lo < hi) { | |
// System.out.println("pos"+pos); | |
if (pos < k) | |
lo = pos + 1; | |
else if (pos > k) | |
hi = pos - 1; | |
else | |
break; | |
pos = partition(arr, lo, hi); | |
} | |
return arr[pos]; | |
} | |
static void shuffleArray(int[] array) { | |
Random random = new Random(); | |
for (int i = array.length - 1; i > 0; i--) { | |
int index = random.nextInt(i + 1); | |
int temp = array[index]; | |
array[index] = array[i]; | |
array[i] = temp; | |
} | |
} | |
private static <Key> void frequency(Map<Key, Integer> mp, Key k) { | |
Integer query = mp.get(k); | |
mp.put(k, query == null ? 1 : query + 1); | |
} | |
static class MultiSet<T> extends HashMap<T, Integer> { | |
public void add(T key) { | |
Integer q = super.get(key); | |
if (q == null) | |
super.put(key, 1); | |
else | |
super.put(key, q + 1); | |
} | |
@Override | |
public Integer remove(Object key) { | |
Integer q = super.get(key); | |
if (q != null) { | |
if (q == 1) | |
super.remove(key); | |
else | |
super.put((T) key, q - 1); | |
} else | |
throw new NullPointerException("The specified key does not exist"); | |
return q; | |
} | |
} | |
public static HashMap<Character, Integer> freqOfChar(String str) { | |
HashMap<Character, Integer> mp = new HashMap<>(); | |
for (int i = 0, len = str.length(); i < len; i++) { | |
char k = str.charAt(i); | |
Integer query = mp.get(k); | |
if (query == null) | |
mp.put(k, new Integer(1)); | |
else { | |
mp.put(k, query + 1); | |
} | |
} | |
return mp; | |
} | |
private static String filter(String str) // Removes duplicate chars in a | |
// string | |
{ | |
HashSet<Character> filter = new HashSet<>(); | |
StringBuilder sb = new StringBuilder(); | |
for (char c : str.toCharArray()) { | |
if (!filter.contains(c)) { | |
filter.add(c); | |
sb.append(c); | |
} | |
} | |
return sb.toString(); | |
} | |
static boolean canPalin(String str) { | |
TreeMap<Character, Integer> freq = new TreeMap<>(); | |
int len = str.length(); | |
for (int i = 0; i < len; i++) | |
frequency(freq, str.charAt(i)); | |
if (len % 2 == 0) { | |
for (Map.Entry<Character, Integer> e : freq.entrySet()) | |
if (e.getValue() % 2 == 1) | |
return false; | |
return true; | |
} else { | |
int ct = 0; | |
for (Map.Entry<Character, Integer> e : freq.entrySet()) { | |
if (e.getValue() % 2 == 1) | |
ct++; | |
if (ct > 1) | |
return false; | |
} | |
return true; | |
} | |
} | |
public static BitSet isPrimeBitSet(int N) {// Sieve of Erathanoses | |
BitSet bs = new BitSet(N + 1); | |
bs.set(0, bs.size()); | |
bs.set(0, false); | |
bs.set(1, false); | |
for (int i = 2; i * i <= N; i++) | |
if (bs.get(i)) // i is prime | |
for (int j = i * i; j <= N; j += i) | |
bs.set(j, false); | |
return bs; | |
} | |
public static boolean[] isPrimeArray(int N) // Sieve of Erathanoses | |
{ | |
boolean num[] = new boolean[N + 1]; | |
Arrays.fill(num, true); | |
num[1] = num[0]= false; | |
for (int i = 2; i * i <= N; i++) | |
if (num[i]) // i is prime | |
for (int j = i * i; j <= N; j += i) | |
num[j] = false; | |
return num; | |
} | |
public static int[] sieve(int N) // Sieve of Erathanoses dependency : isPrimeArray() | |
{ | |
boolean isPrime[] = isPrimeArray(N); | |
int sz = 0; | |
for(boolean b : isPrime) | |
sz += b ? 1 : 0; | |
int arr[] = new int[sz]; | |
int ptr = 0; | |
for (int i = 2; i <= N; i++) | |
if (isPrime[i]) | |
arr[ptr++] = i; | |
return arr; | |
} | |
public static boolean isPalin(String str) { | |
int len = str.length(); | |
int end = len / 2; | |
for (int i = 0; i < end; i++) | |
if (str.charAt(i) != str.charAt(len - i - 1)) | |
return false; | |
return true; | |
} | |
static long gcd(long a , long b) { return (b == 0) ? a : gcd(b, a % b); } | |
public static ArrayList<Integer> palindromes(int start, int end) { | |
ArrayList<Integer> palins = new ArrayList<>(); | |
for (int i = start; i <= end; i++) { | |
if (isPalin(String.valueOf(i))) | |
palins.add(i); | |
} | |
return palins; | |
} | |
static long nCk(int n, int k) { | |
if (n == k) | |
return 1; | |
long ans = 1; | |
k = (int) Math.min(k, n - k); | |
for (int i = 1; i <= k; i++, n--) { | |
if (n % i == 0) { | |
ans *= (n / i); | |
} else if (ans % i == 0) { | |
ans = (ans / i) * n; | |
} else { | |
ans = (ans * n) / i; | |
} | |
} | |
return ans; | |
} | |
class MyMap<K, V> extends HashMap<K, ArrayList<V>> { | |
private static final long serialVersionUID = 1L; // don't know what it | |
// is but eclipse gives | |
// me a warning | |
public MyMap() { | |
super(); | |
} | |
@Override | |
public ArrayList<V> put(K key, ArrayList<V> value) { | |
return super.put(key, value); | |
} | |
public void putVal(K key, V value) { | |
ArrayList<V> arl = get(key); | |
if (arl == null) { | |
arl = new ArrayList<>(); | |
arl.add(value); | |
} else | |
arl.add(value); | |
put(key, arl); | |
} | |
} | |
class FasterScanner { | |
private byte[] buf = new byte[1024]; | |
private int tmp_curChar; | |
private int tmp_numChars; | |
public int read() { | |
if (tmp_numChars == -1) | |
throw new InputMismatchException(); | |
if (tmp_curChar >= tmp_numChars) { | |
tmp_curChar = 0; | |
try { | |
tmp_numChars = System.in.read(buf); | |
} catch (IOException e) { | |
throw new InputMismatchException(); | |
} | |
if (tmp_numChars <= 0) | |
return -1; | |
} | |
return buf[tmp_curChar++]; | |
} | |
public String nextLine() { | |
int c = read(); | |
while (isSpaceChar(c)) | |
c = read(); | |
StringBuilder res = new StringBuilder(); | |
do { | |
res.appendCodePoint(c); | |
c = read(); | |
} while (!isEndOfLine(c)); | |
return res.toString(); | |
} | |
public String next() { | |
int c = read(); | |
while (isSpaceChar(c)) | |
c = read(); | |
StringBuilder res = new StringBuilder(); | |
do { | |
res.appendCodePoint(c); | |
c = read(); | |
} while (!isSpaceChar(c)); | |
return res.toString(); | |
} | |
public long nextLong() { | |
int c = read(); | |
while (isSpaceChar(c)) | |
c = read(); | |
int sgn = 1; | |
if (c == '-') { | |
sgn = -1; | |
c = read(); | |
} | |
long res = 0; | |
do { | |
if (c < '0' || c > '9') | |
throw new InputMismatchException(); | |
res *= 10; | |
res += c - '0'; | |
c = read(); | |
} while (!isSpaceChar(c)); | |
return res * sgn; | |
} | |
public int nextInt() { | |
int c = read(); | |
while (isSpaceChar(c)) | |
c = read(); | |
int sgn = 1; | |
if (c == '-') { | |
sgn = -1; | |
c = read(); | |
} | |
int res = 0; | |
do { | |
if (c < '0' || c > '9') | |
throw new InputMismatchException(); | |
res *= 10; | |
res += c - '0'; | |
c = read(); | |
} while (!isSpaceChar(c)); | |
return res * sgn; | |
} | |
public int[] nextIntArray(int n) { | |
int[] arr = new int[n]; | |
for (int i = 0; i < n; i++) { | |
arr[i] = nextInt(); | |
} | |
return arr; | |
} | |
public long[] nextLongArray(int n) { | |
long[] arr = new long[n]; | |
for (int i = 0; i < n; i++) { | |
arr[i] = nextLong(); | |
} | |
return arr; | |
} | |
private boolean isSpaceChar(int c) { | |
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; | |
} | |
private boolean isEndOfLine(int c) { | |
return c == '\n' || c == '\r' || c == -1; | |
} | |
} | |
class Pair<A, B> { | |
public final A first; | |
public final B second; | |
public Pair(final A first, final B second) { | |
this.first = first; | |
this.second = second; | |
} | |
public boolean equals(Pair<A, B> that) { | |
return this.first.equals(that.first) && this.second.equals(that.second); | |
} | |
} | |
static class AVLTree { | |
static class Node { | |
long key; | |
long sum; | |
int height; | |
int cnt; | |
int size; | |
Node left, right, parent; | |
Node(long key) { | |
this.key = key; | |
height = 1; | |
sum = key; | |
cnt = 1; | |
size = 1; | |
left = right = parent = null; | |
} | |
@Override | |
public String toString() { | |
return "[key = " + key + " s = " +sum + "cnt = "+cnt+" sz = "+size+ "]" + " P = " + (parent != null ? parent.key : "null") | |
+ " L = " + (left != null ? left.key : "null") + " R = " + (right != null ? right.key : "null"); | |
} | |
} | |
public Node root; | |
public AVLTree() { | |
root = null; | |
} | |
public int height(Node n) { | |
return n == null ? 0 : n.height; | |
} | |
public void add(long key) { | |
root = add(key, root, null); | |
Node N = search(root, key); | |
root = rebalance(N); | |
} | |
public boolean find(long key) { | |
return search(root, key) != null; | |
} | |
public long sum(Node n) { | |
return n == null ? 0 : n.sum; | |
} | |
public int size(Node n){ | |
return n == null ? 0 : n.size; | |
} | |
public void adjustHeight(Node N) { | |
N.height = 1 + Math.max(height(N.left), height(N.right)); | |
if (N.left != null) | |
N.left.parent = N; | |
if (N.right != null) | |
N.right.parent = N; | |
adjustSum(N); // Small hack , so that I need not call it explicitly!! | |
adjustSize(N); | |
} | |
public void adjustSum(Node N) { | |
N.sum = (N.key * (long)N.cnt) + sum(N.left) + sum(N.right); | |
} | |
public void adjustSize(Node N){ | |
N.size = N.cnt + size(N.left) + size(N.right); | |
} | |
public Node rotateRight(Node N) { | |
Node oldPar = N.parent; | |
Node newN = N.left; | |
N.left = newN.right; | |
if (newN != null && newN.right != null && newN.right.parent != null) | |
newN.right.parent = N; | |
adjustHeight(N); | |
newN.parent = oldPar; | |
newN.right = N; | |
adjustHeight(newN); | |
N.parent = newN; | |
if (oldPar != null) { | |
if (oldPar.left == N) | |
oldPar.left = newN; | |
else | |
oldPar.right = newN; | |
adjustHeight(oldPar); | |
} | |
return newN; | |
} | |
public Node rotateLeft(Node N) { | |
Node oldPar = N.parent; | |
Node newN = N.right; | |
N.right = newN.left; | |
if (newN != null && newN.left != null && newN.left.parent != null) | |
newN.left.parent = N; | |
adjustHeight(N); | |
newN.parent = oldPar; | |
newN.left = N; | |
N.parent = newN; | |
adjustHeight(newN); | |
if (oldPar != null) { | |
if (oldPar.left == N) | |
oldPar.left = newN; | |
else | |
oldPar.right = newN; | |
adjustHeight(oldPar); | |
} | |
return newN; | |
} | |
public Node search(Node root, long key) { | |
if (root != null) | |
return ((root.key == key) ? root : (key < root.key ? search(root.left, key) : search(root.right, key))); | |
else | |
return null; | |
} | |
public Node smallest(Node root) { | |
return (root.left == null) ? root : smallest(root.left); | |
} | |
public Node largest(Node root) { | |
return (root.right == null) ? root : largest(root.right); | |
} | |
public void del(long key) { | |
Node toBeRemoved = search(root, key); | |
if (toBeRemoved != null) { | |
if (toBeRemoved.cnt == 1) | |
delete(toBeRemoved); | |
else { | |
toBeRemoved.cnt--; | |
while (toBeRemoved != null) { | |
adjustHeight(toBeRemoved); | |
toBeRemoved = toBeRemoved.parent; | |
} | |
} | |
} | |
} | |
public long sumInRange(long L, long R ) { | |
return (sumStrictlyLess(root, R) - sumStrictlyLess(root, L)); // [L,R) | |
} | |
public long sumStrictlyLess(Node root, long key) { | |
if (root != null) { | |
if (root.key == key) | |
return sum(root.left); | |
else if (key < root.key) | |
return sumStrictlyLess(root.left, key); | |
else | |
return (root.key * (long)(root.cnt)) + sum(root.left) + sumStrictlyLess(root.right, key); | |
} else | |
return 0; | |
} | |
public int countGreater(Node root , long key) | |
{ | |
if(root != null){ | |
if(root.key == key){ | |
return size(root.right); | |
} | |
else if(root.key < key){ | |
return countGreater(root.right, key); | |
} | |
else | |
return root.cnt + size(root.right) + countGreater(root.left, key); | |
} | |
else | |
return 0; | |
} | |
public int countGreater(long key){ | |
return countGreater(root, key); | |
} | |
public void delete(Node N) { | |
if (N.left == null && N.right == null) { | |
if (N == root) | |
root = null; | |
else { | |
Node par = N.parent; | |
if (par.left == N) | |
par.left = null; | |
else | |
par.right = null; | |
Node orig_par = par; | |
while (par != null) { | |
adjustHeight(par); | |
par = par.parent; | |
} | |
root = rebalance(orig_par); | |
} | |
} else if (N.right == null && N.left != null) { | |
Node par = N.parent; | |
if (par != null) { | |
if (par.left == N) | |
par.left = N.left; | |
else | |
par.right = N.left; | |
N.left.parent = par; | |
Node orig_par = par; | |
while (par != null) { | |
adjustHeight(par); | |
par = par.parent; | |
} | |
root = rebalance(orig_par); | |
} else { | |
root = root.left; | |
root.parent = null; | |
adjustHeight(root); | |
} | |
} else if (N.left == null && N.right != null) { | |
Node par = N.parent; | |
if (par != null) { | |
if (par.left == N) | |
par.left = N.right; | |
else | |
par.right = N.right; | |
N.right.parent = par; | |
Node orig_par = par; | |
while (par != null) { | |
adjustHeight(par); | |
par = par.parent; | |
} | |
root = rebalance(orig_par); | |
} else { | |
root = root.right; | |
root.parent = null; | |
adjustHeight(root); | |
} | |
} else { | |
Node small = smallest(N.right); | |
N.key = small.key; | |
N.cnt = small.cnt; // !!! VERY VERY IMPORTANT | |
delete(small); | |
} | |
} | |
public Node rebalance(Node N) { | |
Node par = N.parent; | |
if (height(N.left) - height(N.right) >= 2) { | |
Node M = N.left; | |
if (height(M.right) > height(M.left)) | |
M = rotateLeft(M); | |
N = rotateRight(N); | |
} | |
if (height(N.right) - height(N.left) >= 2) { | |
Node M = N.right; | |
if (height(M.left) > height(M.right)) | |
M = rotateRight(M); | |
N = rotateLeft(N); | |
} | |
if (par != null) | |
return rebalance(par); | |
else | |
return N; | |
} | |
public Node add(long key, Node root, Node parent) { | |
if (root == null) { | |
Node newNode = new Node(key); | |
newNode.parent = parent; | |
return newNode; | |
} else { | |
if (key < root.key) | |
root.left = add(key, root.left, root); | |
else if (key > root.key) | |
root.right = add(key, root.right, root); | |
else | |
root.cnt++; | |
adjustHeight(root); | |
return root; | |
} | |
} | |
public void print(Node root) { | |
if (root != null) { | |
print(root.left); | |
System.out.println(root); | |
print(root.right); | |
} | |
} | |
private StringBuilder toString(StringBuilder prefix, boolean isTail, StringBuilder sb, Node root) { | |
if (root == null) { | |
sb.append("Tree Empty\n"); | |
return sb; | |
} | |
if (root.right != null) { | |
toString(new StringBuilder().append(prefix).append(isTail ? "| " : " "), false, sb, root.right); | |
} | |
sb.append(prefix).append(isTail ? "|-- " : "|-- ").append(root.key).append("\n"); | |
if (root.left != null) { | |
toString(new StringBuilder().append(prefix).append(isTail ? " " : "| "), true, sb, root.left); | |
} | |
return sb; | |
} | |
@Override | |
public String toString() { | |
return this.toString(new StringBuilder(), true, new StringBuilder(), root).toString(); | |
} | |
} | |
static class SplayTree /** The following implementation does not allow duplicates **/{ | |
private Vertex root = null; | |
static class Vertex { | |
int key; | |
// Sum of all the keys in the subtree - remember to update | |
// it after each operation that changes the tree. | |
long sum; | |
Vertex left; | |
Vertex right; | |
Vertex parent; | |
Vertex(int key, long sum, Vertex left, Vertex right, Vertex parent) { | |
this.key = key; | |
this.sum = sum; | |
this.left = left; | |
this.right = right; | |
this.parent = parent; | |
} | |
@Override | |
public String toString() { | |
return "[key = " + key + "]" + " p = " + (parent != null ? parent.key : "null") + " l = " | |
+ (left != null ? left.key : "null") + " r = " + (right != null ? right.key : "null"); | |
} | |
} | |
static class VertexPair { | |
Vertex left; | |
Vertex right; | |
VertexPair() { | |
} | |
VertexPair(Vertex left, Vertex right) { | |
this.left = left; | |
this.right = right; | |
} | |
} | |
private void update(Vertex v) { | |
if (v == null) | |
return; | |
v.sum = (v.key + (v.left != null ? v.left.sum : 0) + (v.right != null ? v.right.sum : 0)); | |
if (v.left != null) { | |
v.left.parent = v; | |
} | |
if (v.right != null) { | |
v.right.parent = v; | |
} | |
} | |
private void smallRotation(Vertex v) { | |
Vertex parent = v.parent; | |
if (parent == null) { | |
return; | |
} | |
Vertex grandparent = v.parent.parent; | |
if (parent.left == v) { | |
Vertex m = v.right; | |
v.right = parent; | |
parent.left = m; | |
} else { | |
Vertex m = v.left; | |
v.left = parent; | |
parent.right = m; | |
} | |
update(parent); | |
update(v); | |
v.parent = grandparent; | |
if (grandparent != null) { | |
if (grandparent.left == parent) { | |
grandparent.left = v; | |
} else { | |
grandparent.right = v; | |
} | |
} | |
update(grandparent); | |
} | |
private void bigRotation(Vertex v) { | |
if (v.parent.left == v && v.parent.parent.left == v.parent) { | |
// Zig-zig left | |
/* a | |
* / | |
* / | |
* b | |
*/ | |
smallRotation(v.parent); | |
smallRotation(v); | |
} else if (v.parent.right == v && v.parent.parent.right == v.parent) { | |
// Zig-zig right | |
/* | |
* a | |
* \ | |
* \ | |
* b | |
*/ | |
smallRotation(v.parent); | |
smallRotation(v); | |
} else { | |
/* Zig-zag | |
* a a | |
* / \ | |
* \ / | |
* b b | |
*/ | |
smallRotation(v); | |
smallRotation(v); | |
} | |
} | |
private Vertex splay(Vertex v) { | |
if (v == null) | |
return null; | |
while (v.parent != null) { | |
if (v.parent.parent != null) | |
bigRotation(v); | |
else | |
smallRotation(v); | |
} | |
return v; | |
} | |
// Searches for the given key in the tree with the given root | |
// and calls splay for the deepest visited node after that. | |
// Returns pair of the result and the new root. | |
// If found, result is a pointer to the node with the given key. | |
// Otherwise, result is a pointer to the node with the smallest | |
// bigger key (next value in the order). | |
// If the key is bigger than all keys in the tree, | |
// then result is null. | |
private VertexPair find(Vertex root, int key) { //searches for a elem and splays the last touched node. | |
Vertex v = root; // Returns a vertex pair with | |
Vertex last = root; // Left node = ceil of the search | |
Vertex next = null; // Right node = last touched node in the search | |
while (v != null) { | |
if (v.key >= key && (next == null || v.key < next.key)) { | |
next = v; | |
} | |
last = v; | |
if (v.key == key) { | |
break; | |
} | |
if (v.key < key) { | |
v = v.right; | |
} else { | |
v = v.left; | |
} | |
} | |
root = splay(last); | |
return new VertexPair(next, root); | |
} | |
private static void print(Vertex root) { | |
if (root != null) { | |
print(root.left); | |
System.out.println(root); | |
print(root.right); | |
} | |
} | |
private VertexPair split(Vertex root, int key) { | |
VertexPair result = new VertexPair(); | |
VertexPair findAndRoot = find(root, key); | |
root = findAndRoot.right; | |
result.right = findAndRoot.left; | |
if (result.right == null) { // Key is largest in the tree | |
result.left = root; | |
return result; | |
} | |
result.right = splay(result.right); | |
result.left = result.right.left; | |
result.right.left = null; | |
if (result.left != null) | |
result.left.parent = null; | |
update(result.left); | |
update(result.right); | |
return result; | |
} | |
private Vertex merge(Vertex left, Vertex right) { | |
if (left == null) | |
return right; | |
if (right == null) | |
return left; | |
left = find(left, Integer.MAX_VALUE).right; // root after the find and splay , Find the max in left tree | |
left.right = right; | |
left.parent = null; | |
update(left); | |
return left; | |
} | |
public void insert(int x) { // Split the tree at x and then the left tree has all elements less | |
if (!find(x)) { // than x and right tree has all elements greater now create a new node | |
Vertex left = null; // and merge the left-->new node-->right | |
Vertex right = null; | |
Vertex new_vertex = null; | |
VertexPair leftRight = split(root, x); | |
left = leftRight.left; | |
right = leftRight.right; | |
if (right == null || right.key != x) { | |
new_vertex = new Vertex(x, x, null, null, null); | |
} | |
root = merge(merge(left, new_vertex), right); | |
root.parent = null; | |
update(root); | |
} | |
} | |
public void erase(int x) { | |
VertexPair vp = find(root, x); | |
root = vp.right; | |
if (root != null) | |
root.parent = null; | |
update(root); | |
if (vp.right != null && vp.right.key == x) { | |
if (vp.right.right == null) { | |
root = vp.right.left; | |
if (root != null) | |
root.parent = null; | |
update(root); | |
} else { //First splay the ceil of x then splay x now the ceil of x is in the right , | |
find(root, x + 1); //so we can just redirect the root = root.right | |
vp = find(root, x); | |
root = vp.right.right; | |
root.left = vp.right.left; | |
root.parent = null; | |
update(root); | |
} | |
} | |
} | |
public boolean find(int x) { | |
VertexPair vp = find(root, x); | |
root = vp.right; | |
return root != null && root.key == x; | |
} | |
public long sum(int from, int to) { | |
VertexPair leftMiddle = split(root, from); | |
Vertex left = leftMiddle.left; | |
Vertex middle = leftMiddle.right; | |
VertexPair middleRight = split(middle, to + 1); | |
middle = middleRight.left; | |
Vertex right = middleRight.right; | |
long ans = middle != null ? middle.sum : 0; | |
root = merge(left, merge(middle, right)); | |
return ans; | |
} | |
private StringBuilder toString(StringBuilder prefix, boolean isTail, StringBuilder sb, Vertex root) { | |
if (root == null) { | |
sb.append("Tree Empty"); | |
return sb; | |
} | |
if (root.right != null) { | |
toString(new StringBuilder().append(prefix).append(isTail ? "│ " : " "), false, sb, root.right); | |
} | |
sb.append(prefix).append(isTail ? "└── " : "┌── ").append(root.key).append("\n"); | |
if (root.left != null) { | |
toString(new StringBuilder().append(prefix).append(isTail ? " " : "│ "), true, sb, root.left); | |
} | |
return sb; | |
} | |
@Override | |
public String toString() { | |
return this.toString(new StringBuilder(), true, new StringBuilder(), root).toString(); | |
} | |
} | |
static int mod = 1000000007; | |
static class Matrix { // Don't use ModMath class with Matrix (very slow in matrix exponentiation) | |
long e00, e01, e10, e11; | |
Matrix(long a, long b, long c, long d) { | |
e00 = a; | |
e01 = b; | |
e10 = c; | |
e11 = d; | |
} | |
Matrix multiply(Matrix t) { | |
long a = (((e00 * t.e00) % mod) + ((e01 * t.e10) % mod)) % mod; | |
long b = (((e00 * t.e01) % mod) + ((e01 * t.e11) % mod)) % mod; | |
long c = (((e10 * t.e00) % mod) + ((e11 * t.e10) % mod)) % mod; | |
long d = (((e10 * t.e01) % mod) + ((e11 * t.e11) % mod)) % mod; | |
return new Matrix(a, b, c, d); | |
} | |
public String toString() { | |
return e00 + " " + e01 + "\n" + e10 + " " + e11 + "\n"; | |
} | |
static long mul(long a, long b) { | |
return ((a % mod) * (b % mod)) % mod; | |
} | |
static long add(long a, long b) { | |
return ((a % mod) + (b % mod)) % mod; | |
} | |
} | |
public static Matrix pow(Matrix m, int b) { | |
if (b == 1) | |
return m; | |
else { | |
if ((b & 1) == 0) | |
return pow(m.multiply(m), b >> 1); | |
else | |
return m.multiply(pow(m.multiply(m), b >> 1)); | |
} | |
} | |
static class MyBitSet { | |
long bits[]; | |
int cardinality; | |
int size; | |
MyBitSet(int MAX) { | |
size = MAX; | |
bits = new long[((MAX - 1) / 64) + 1]; | |
cardinality = 0; | |
} | |
void set(int n, boolean f) { | |
int index = n / 64; | |
if (f) { | |
if((bits[index] & (1L << (n % 64))) == 0) | |
cardinality++; | |
bits[index] |= (1L << (n % 64)); | |
} | |
else | |
bits[index] ^= (bits[index] & (1L << (n % 64))) != 0 ? (1L << (n % 64)) : 0; | |
} | |
void set(int n) { | |
set(n, true); | |
} | |
int cardinality() { | |
return cardinality; | |
} | |
boolean get(int n) { | |
return ((bits[n / 64]) & (1L << (n % 64))) != 0; | |
} | |
} | |
/* Increase stack size in java | |
*/ | |
public static void main(String[] args) throws IOException { | |
new Thread(null, new Runnable() { | |
public void run() { | |
new helper().run(); | |
} | |
}, "Increase Stack", 1 << 25).start(); | |
} | |
void run(){ | |
} | |
static class DSU { | |
private int parent[]; | |
private int size[]; | |
private int cnt; | |
DSU(int length) { | |
this.cnt = length; | |
parent = new int[length + 10]; | |
size = new int[length + 10]; | |
Arrays.fill(size, 1); | |
for (int i = 0; i < parent.length; i++) | |
parent[i] = i; | |
} | |
int root(int p) { | |
while(p != parent[p]) p = parent[p]; | |
return p; | |
} | |
int sizeOf(int p) { | |
return size[root(p)]; | |
} | |
boolean connected(int u, int v) { | |
return root(u) == root(v); | |
} | |
int components() { | |
return cnt; | |
} | |
void union(int u, int v) { | |
if (!connected(u, v)) { | |
cnt--; | |
int rootU = root(u); | |
int rootV = root(v); | |
if (size[rootU] < size[rootV]) { | |
parent[rootU] = rootV; | |
size[rootV] += size[rootU]; | |
} else { | |
parent[rootV] = rootU; | |
size[rootU] += size[rootV]; | |
} | |
} | |
} | |
} | |
private static long distTo[]; // Should be filled with infinity | |
private static ArrayList<Edge>[] adj; | |
static class Edge implements Comparable<Edge> { | |
int v; | |
long cost; | |
Edge(int v, long cost) { | |
this.v = v; | |
this.cost = cost; | |
} | |
@Override | |
public int compareTo(Edge o) { | |
return Long.compare(this.cost, o.cost); | |
} | |
} | |
private static void dijkstra(int start) { | |
PriorityQueue<Edge> pq = new PriorityQueue<>(); | |
pq.add(new Edge(start, 0)); | |
distTo[start] = 0; | |
while (!pq.isEmpty()) { | |
Edge min = pq.remove(); | |
int u = min.v; | |
if (distTo[u] < min.cost) | |
continue; | |
for (Edge e : adj[u]) | |
if (distTo[e.v] > distTo[u] + e.cost) { | |
distTo[e.v] = distTo[u] + e.cost; | |
pq.add(new Edge(e.v, distTo[e.v])); | |
} | |
} | |
} | |
static class Edge_MST implements Comparable<Edge_MST> // For kruskal MST | |
{ | |
int u, v; | |
long cost; | |
Edge_MST(int u, int v, long cost) { | |
this.u = u; | |
this.v = v; | |
this.cost = cost; | |
} | |
@Override | |
public int compareTo(Edge_MST o) { | |
return Long.compare(this.cost, o.cost); | |
} | |
} | |
private static long KruskalMST(Edge_MST arr[], int V) { | |
Arrays.sort(arr); | |
DSU dsu = new DSU(V); | |
long minCost = 0; | |
for (int i = 0; i < arr.length && dsu.components() != 1; i++) { | |
if (!dsu.connected(arr[i].u, arr[i].v)) { | |
dsu.union(arr[i].u, arr[i].v); | |
minCost += arr[i].cost; | |
} | |
} | |
return minCost; | |
} | |
private static void reverse(int arr[]) { | |
for (int i = 0, end = arr.length >> 1; i < end; i++) { | |
int temp = arr[i]; | |
arr[i] = arr[arr.length - i - 1]; | |
arr[arr.length - i - 1] = temp; | |
} | |
} | |
static class MMInt { // MM (Modular Math) class | |
static final int mod = (int) (1e9) + 7; // Default | |
static int sub(int a, int b) {return (a - b + mod) % mod;} | |
static int mul(int a, int b) {return (int) ((1L * a * b ) % mod);} | |
static int add(int a, int b) {return (a + b) % mod;} | |
static int div(int a, int b) {return mul(a, modInverse(b));} | |
static int modInverse(int n) {return modPow(n, mod - 2);} // Fermat's little theorem | |
static int modPow(long a , long b) { | |
long pow = 1; | |
while(b > 0) { | |
if((b & 1L) == 1) | |
pow = ((pow * a) % mod); | |
a = ((a * a) % (mod)); | |
b >>= 1; | |
} | |
return (int) pow; | |
} | |
} | |
static class MM { // MM (Modular Math) class | |
static final long mod = (long) (1e9) + 7; // Default | |
static long sub(long a, long b) {return (a - b + mod) % mod;} | |
static long mul(long a, long b) {return ((a % mod) * (b % mod)) % mod;} | |
static long add(long a, long b) {return (a + b) % mod;} | |
static long div(long a, long b) {return mul(a, modInverse(b));} | |
static long modInverse(long n) {return modPow(n, mod - 2);} // Fermat's little theorem | |
static long modPow(long a , long b) { | |
long pow = 1; | |
while(b > 0) { | |
if((b & 1L) == 1) | |
pow = ((pow * a) % mod); | |
a = ((a * a) % (mod)); | |
b >>= 1; | |
} | |
return pow; | |
} | |
} | |
private static int MAX = 1000_000; // (Change it to max N limit (be careful with the index) | |
private static long fact[] = new long[MAX + 5]; | |
private static long invFact[] = new long[MAX + 5]; | |
static { | |
fact[1] = 1; | |
fact[0] = 1; | |
for (int i = 2; i <= MAX; i++) | |
fact[i] = MM.mul(i, fact[i - 1]); | |
for(int i=0;i<=MAX;i++) | |
invFact[i] = MM.modInverse(fact[i]); | |
} | |
private static long nCr(int n, int r) { // Precompute inv Factorials (Dont compute every time) | |
return MM.mul(fact[n], MM.mul(invFact[r], invFact[n - r])); | |
} | |
static class SparseTable2D // <O (MNlog(M)log(N)) , O(1) > | |
{ | |
/* | |
* Dont use Math.log its (very * 2 ^ 64) slow for a lot of queries (10^6), | |
* instead precompute the log values . or use log(n) = (31 - Integer.numberOfLeadingZeros(n)) | |
* Costed me several days | |
* | |
* In a sparse table you break the query rectangle into four smaller rects each with | |
* dimensions log(height) X log(width) | |
* | |
* So the query time is O(1) , but the build time is O(M * N * log(M) * log(N)) | |
* | |
* ********|****|****** | |
* ********|****|****** | |
* ********|****|****** | |
* --------|----|------ | |
* ****************** | |
* ****************** | |
*/ | |
int sparse[][][][]; | |
static int log(int N) { return 31 - Integer.numberOfLeadingZeros(N); } | |
int R,C; | |
int getMax(int x1,int y1,int x2,int y2, boolean build){ | |
int x_sz = x2 - x1 + 1; | |
int y_sz = y2 - y1 + 1; | |
int k1 = (x_sz == 1) ? 0 : log(build ? (x_sz - 1) : x_sz); | |
int k2 = (y_sz == 1) ? 0 : log(build ? (y_sz - 1) : y_sz); | |
int NW = sparse[k1][k2][x1][y1]; // North-West | |
int NE = sparse[k1][k2][x1][y_sz - (1 << k2) + y1]; // North-East | |
int SW = sparse[k1][k2][x_sz - (1 << k1) + x1][y1]; // South-West | |
int SE = sparse[k1][k2][x_sz - (1 << k1) + x1][y_sz - (1 << k2) + y1]; // South-East | |
return (int) Math.max(Math.max(NW, NE), Math.max(SW, SE)); | |
} | |
SparseTable2D(int arr[][],int R,int C) | |
{ | |
this.R = R; | |
this.C = C; | |
int k1 = log(R) + 1; | |
int k2 = log(C) + 1; | |
sparse = new int[k1][k2][R][C]; | |
for (int i = 0; i < R; i++) | |
for (int j = 0; j < C; j++) | |
sparse[0][0][i][j] = arr[i][j]; | |
for(int h=0;h<k1;h++) | |
{ | |
for(int v=0;v<k2;v++) | |
{ | |
if(!(h == 0 && v == 0)) | |
{ | |
for(int i=0;i+(1<<h) <= R;i++) | |
{ | |
for(int j=0;j+(1<<v) <= C;j++) | |
{ | |
sparse[h][v][i][j] = getMax(i, j, i + (1<<h) - 1, j + (1<<v) - 1, true); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
static class SparseTable1D // < O(Nlog(N)) , O(1) > 0 based indexing | |
{ | |
int sparse[][]; | |
int len; | |
static int log(int N) { return 31 - Integer.numberOfLeadingZeros(N); } | |
SparseTable1D(int arr[]) | |
{ | |
len = arr.length; | |
int k = log(len) + 1; | |
sparse = new int[k][len]; | |
for (int i = 0; i < len; i++) | |
sparse[0][i] = arr[i]; | |
for(int i=1;i<k;i++) | |
for(int j=0;j+(1<<i) <= len;j++) | |
sparse[i][j] = Math.max(sparse[i-1][j],sparse[i-1][j+(1<<(i-1))]); | |
} | |
int getMax(int L,int R) | |
{ | |
int sz = R - L + 1; | |
int k = log(sz); | |
int v1 = sparse[k][L]; | |
int v2 = sparse[k][L + (sz - (1 << k))]; | |
return Math.max(v1,v2); | |
} | |
} | |
static class Vector { | |
double x, y; | |
private double norm; | |
public String toString() { | |
return String.format("(%.3f , %.3f)", x , y); | |
} | |
Vector(double x, double y) { | |
this.x = x; | |
this.y = y; | |
this.norm = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); | |
} | |
Vector() { | |
this(0, 0); | |
} | |
double magnitude() { | |
return norm; | |
} | |
double angleTo(Vector that) { | |
double cosTheta = ((this.x * that.x) + (this.y * that.y)) / (this.magnitude() * that.magnitude()); | |
return Math.acos(cosTheta); | |
} | |
Vector add(Vector that) { | |
return new Vector(this.x + that.x, this.y + that.y); | |
} | |
static Vector[] getPerpendicularUnit(Vector v) { | |
Vector[] vecs = new Vector[2]; | |
double constant; | |
if(v.x == 0) { | |
constant = 1.0 / Math.sqrt(1.0 + ((v.x * v.x) / (v.y * v.y))); | |
vecs[0] = new Vector(constant, -constant * (v.x / v.y)); | |
} | |
else { | |
constant = 1.0 / Math.sqrt(1.0 + ((v.y * v.y) / (v.x * v.x))); | |
vecs[0] = new Vector(-constant * (v.y / v.x), constant); | |
} | |
vecs[1] = new Vector(-vecs[0].x, -vecs[0].y); | |
return vecs; | |
} | |
void multiply(double scalar) { | |
x *= scalar; | |
y *= scalar; | |
norm *= scalar; | |
} | |
} | |
static class MyFreqMap // Order statistics on elements | |
{ | |
HashMap<Integer,Integer> freq; | |
TreeMap<Integer,TreeSet<Integer>> inverse; | |
MyFreqMap(){ | |
freq = new HashMap<>(); | |
inverse = new TreeMap<>(); | |
} | |
void addIntoMap(int key,int val){ | |
TreeSet<Integer> set = inverse.get(key); | |
if(set == null) | |
set = new TreeSet<>(); | |
set.add(val); | |
inverse.put(key, set); | |
} | |
void removeFromMap(int key1,int key2){ | |
TreeSet<Integer> set = inverse.get(key1); | |
set.remove(key2); | |
if(set.size() == 0) | |
inverse.remove(key1); | |
else | |
inverse.put(key1, set); | |
} | |
void add(int elem){ | |
int oldFreq = freq.getOrDefault(elem, 0); | |
if(oldFreq == 0){ | |
freq.put(elem, 1); | |
addIntoMap(1, elem); | |
} | |
else{ | |
freq.put(elem, oldFreq + 1); | |
removeFromMap(oldFreq, elem); | |
addIntoMap(oldFreq + 1, elem); | |
} | |
} | |
void remove(int elem){ | |
int oldFreq = freq.get(elem); | |
if(oldFreq == 1){ | |
freq.remove(elem); | |
removeFromMap(1, elem); | |
} | |
else{ | |
freq.put(elem, oldFreq - 1); | |
removeFromMap(oldFreq, elem); | |
addIntoMap(oldFreq - 1, elem); | |
} | |
} | |
int getMaxFreqElem(){ | |
return inverse.lastEntry().getValue().first(); | |
} | |
@Override | |
public String toString() { | |
return " freq = " + freq + " inv " + inverse; | |
} | |
} | |
static class SuffixArray { // Implemented for Upper case alphabets automatically appends ' $ ' | |
final char $ = '@'; // use ' ` ' for small case alphabets | |
int equiClass[]; | |
int order[]; | |
int N; | |
int add(int a, int b){ return (a + b) % N; } | |
int sub(int a ,int b){ return (N + a - b) % N; } | |
int[] sortDoubled(int L){ | |
int newOrder[] = new int[N]; | |
int cnt[] = new int[N]; | |
for(int i=0;i<N;i++){ | |
int idx = sub(order[i], L); | |
cnt[equiClass[idx]]++; | |
} | |
for(int i=1;i<N;i++) | |
cnt[i] += cnt[i - 1]; | |
for(int i=N-1;i>=0;i--){ | |
int idx = sub(order[i], L); | |
newOrder[--cnt[equiClass[idx]]] = idx; | |
} | |
return newOrder; | |
} | |
int[] updateEquiClass(int L , int newOrder[]){ | |
int newClass[] = new int[N]; | |
newClass[newOrder[0]] = 0; | |
for(int i=1;i<N;i++){ | |
int f1 = equiClass[newOrder[i - 1]]; | |
int s1 = equiClass[add(newOrder[i - 1], L)]; | |
int f2 = equiClass[newOrder[i]]; | |
int s2 = equiClass[add(newOrder[i], L)]; | |
newClass[newOrder[i]] = newClass[newOrder[i - 1]] + (f1 == f2 && s1 == s2 ? 0 : 1); | |
} | |
return newClass; | |
} | |
int[] getSuffixArray(){ | |
for(int L = 1;L < N;L <<= 1){ | |
int[] newOrder = sortDoubled(L); | |
int[] newClass = updateEquiClass(L, newOrder); | |
order = newOrder; | |
equiClass = newClass; | |
} | |
return order; | |
} | |
SuffixArray(String str){ | |
str = str.concat(String.valueOf($)); | |
N = str.length(); | |
equiClass = new int[N]; | |
order = new int[N]; | |
int cnt[] = new int[27]; | |
for(int i=0;i<N;i++) | |
cnt[str.charAt(i) - $]++; | |
for(int i=1;i<27;i++) | |
cnt[i] += cnt[i - 1]; | |
for(int i=N-1;i>=0;i--) | |
order[--cnt[str.charAt(i) - $]] = i; | |
equiClass[order[0]] = 0; | |
for(int i=1;i<N;i++) | |
equiClass[order[i]] = equiClass[order[i - 1]] + (str.charAt(order[i]) == str.charAt(order[i - 1]) | |
? 0 : 1 ); | |
} | |
} | |
/* | |
* Solves the TSP problem in O(N^2 * 2^N) | |
* memo[mask][prev] the shortest path using the set integers in mask where the last vertex visited in prev | |
*/ | |
static int cost[][]; | |
static int memo[][]; | |
static int V; | |
static int TSP(int mask , int prev) { | |
if(memo[mask][prev] != -1) | |
return memo[mask][prev]; | |
else { | |
int dist = Integer.MAX_VALUE; | |
for(int i = 0;i < V;i++) | |
if(i != prev && (mask & (1 << i)) != 0) // Also check for edge between i and prev | |
dist = Math.min(dist,cost[i][prev] + TSP(mask ^ (1 << prev), i)); | |
return memo[mask][prev] = dist; | |
} | |
} | |
static class FenwickTree { | |
/**************** | |
* DONT USE BIT IF YOU UPDATE INDEX 0 (causes infinite loop) | |
******************/ | |
int tree[]; | |
int len; | |
FenwickTree(int len) { | |
this.len = len; | |
tree = new int[len + 10]; | |
} | |
void update(int idx, int val) { | |
if (idx == 0) | |
throw new IndexOutOfBoundsException("BIT IS NOT ZERO INDEXED"); | |
for (; idx <= len; idx += (idx & -idx)) | |
tree[idx] += val; | |
} | |
int query(int idx) { | |
int sum = 0; | |
for (; idx > 0; idx -= (idx & -idx)) | |
sum += tree[idx]; | |
return sum; | |
} | |
int query(int L, int R) { | |
return query(R) - query(L - 1); | |
} | |
} | |
/* LCA <NlogN , logN> dependency : level , log , V , DP = new int[log(V) + 1][V + 1];, parent (for the first level of DP) */ | |
static int DP[][]; // One based vertices | |
static int level[]; | |
static int parent[]; | |
static int log(int N){ | |
return 31 - Integer.numberOfLeadingZeros(N); | |
} | |
static void binaryLift() { | |
for(int i=1;i<=V;i++) | |
DP[0][i] = parent[i]; | |
for (int i = 1; i < DP.length; i++) | |
for (int j = 1; j <= V; j++) | |
DP[i][j] = DP[i - 1][DP[i - 1][j]]; | |
} | |
static int LCA(int u , int v){ | |
if(level[v] < level[u]){ | |
int temp = u; | |
u = v; | |
v = temp; | |
} | |
int diff = level[v] - level[u]; | |
while(diff > 0){ // Bring v to the same level as u | |
int log = log(diff); | |
v = DP[log][v]; | |
diff -= (1 << log); | |
} | |
if(u == v) | |
return u; | |
for(int i = log(level[u]); i >= 0; i--) { | |
if(DP[i][u] != DP[i][v]) { | |
u = DP[i][u]; | |
v = DP[i][v]; | |
} | |
} | |
return DP[0][u]; | |
} | |
static class SegmentTree { // Implemented to store min in a range , point update and range query | |
int tree[]; | |
int len; | |
int size; | |
SegmentTree(int arr[]) { // arr should be a 1 based array | |
len = arr.length - 1; | |
size = 1 << (32 - Integer.numberOfLeadingZeros(len - 1) + 1); // ceil(log(len)) + 1 | |
tree = new int[size]; | |
build(arr, 1, 1, len); | |
} | |
void update(int node,int idx,int val,int nl,int nr) { | |
if(nl == nr && nl == idx) | |
tree[node] = val; | |
else { | |
int mid = (nl + nr) >> 1; | |
if(idx <= mid) | |
update(2*node, idx , val ,nl , mid); | |
else | |
update((2*node) + 1, idx ,val , mid + 1, nr); | |
tree[node] = Math.min(tree[2*node],tree[(2 * node) + 1]); | |
} | |
} | |
void update(int idx , int val){ | |
update(1, idx, val, 1, len); | |
} | |
int query(int L , int R){ | |
return query(1, L, R, 1, len); | |
} | |
int query(int node , int L , int R, int nl, int nr) { | |
int mid = (nl + nr) >> 1; | |
if(nl == L && nr == R) | |
return tree[node]; | |
else if(R <= mid) | |
return query(2 * node, L, R, nl, mid); | |
else if(L > mid) | |
return query((2*node)+1, L, R, mid + 1 , nr); | |
else | |
return Math.min(query(2*node, L, mid , nl , mid) , query((2*node)+1, mid+1, R , mid+1,nr)); | |
} | |
void build(int arr[],int node,int L,int R) { | |
if(L == R) | |
tree[node] = arr[L]; | |
else | |
{ | |
int mid = (L + R) >> 1; | |
build(arr, 2 * node, L, mid); | |
build(arr, (2 * node) + 1, mid + 1, R); | |
tree[node] = Math.min(tree[2*node] , tree[(2 * node) + 1]); | |
} | |
} | |
} | |
static class SCC { | |
/* | |
* Kosaraju-Sharir Algorithm | |
* | |
* Identify sinks (reverse post order in inverse graph) | |
* Start normal dfs from the above order , the resulting components form SCC | |
* | |
* If you want to use 1 based indexing set onBased flag to true | |
* | |
*/ | |
private ArrayList<Integer>[] invGraph; | |
private ArrayDeque<Integer> stack; | |
private Iterable<Integer>[] adj; | |
private int group[]; | |
private boolean marked[]; | |
private int numOfComponents; | |
private int st , V; | |
@SuppressWarnings("unchecked") | |
SCC(Iterable<Integer>[] adj , boolean oneBased) { | |
st = oneBased ? 1 : 0; | |
V = adj.length - st; | |
group = new int[V + st]; | |
this.adj = adj; | |
invGraph = new ArrayList[V + st]; | |
for(int i=st;i<V + st;i++) | |
invGraph[i] = new ArrayList<>(); | |
for(int i=st;i<V + st;i++) | |
for(int j : adj[i]) | |
invGraph[j].add(i); | |
marked = new boolean[V + st]; | |
stack = new ArrayDeque<>(); | |
for(int i=st;i<V + st;i++) | |
if(!marked[i]) | |
reversePostOrder(i); | |
marked = new boolean[V + st]; | |
int grp = 0; | |
for(int i : stack) | |
if(!marked[i]) | |
dfs(i, grp++); | |
numOfComponents = grp; | |
stack = null; | |
} | |
private void reversePostOrder(int u) { | |
marked[u] = true; | |
for(int v : invGraph[u]) | |
if(!marked[v]) | |
reversePostOrder(v); | |
stack.push(u); | |
} | |
private void dfs(int u , int grp) { | |
marked[u] = true; | |
group[u] = grp; | |
for(int v : adj[u]) | |
if(!marked[v]) | |
dfs(v, grp); | |
} | |
public int[] getSCC() { | |
return group; | |
} | |
public int numberOfComponents() { | |
return numOfComponents; | |
} | |
@SuppressWarnings("unchecked") | |
public HashSet<Integer>[] getDAG() { | |
HashSet<Integer>[] dag = new HashSet[numOfComponents]; | |
for(int i=0;i<numOfComponents;i++) | |
dag[i] = new HashSet<>(); | |
for(int i=st;i<V + st;i++) | |
for(int v : adj[i]) | |
if(group[i] != group[v]) | |
dag[group[i]].add(group[v]); | |
return dag; | |
} | |
} | |
static class BellmanFordSSSP { // Dependency : Edge class | |
static class Edge { // Take this Edge class to the outer class | |
int v; | |
long cost; | |
Edge(int vv, long wt) { | |
v = vv; | |
cost = wt; | |
} | |
} | |
static final long INF = (long)3e18; | |
long distTo[]; | |
ArrayList<Edge>[] adj; | |
int V, st; | |
public BellmanFordSSSP(ArrayList<Edge>[] adj , int V , int start, boolean oneBased) { | |
this.V = V; | |
this.adj = adj; | |
st = oneBased ? 1 : 0; | |
distTo = new long[V + st]; | |
Arrays.fill(distTo, INF); | |
distTo[start] = 0; | |
for(int i=1;i<=V-1;i++) | |
for(int u=st;u<V+st;u++) | |
for(Edge e : adj[u]) | |
distTo[e.v] = Math.abs(distTo[u]) == INF ? distTo[e.v] :Math.max(-INF,Math.min(distTo[e.v],distTo[u] + e.cost)); | |
} | |
// Checks wether the graph contains a negative cycle rechable from start or not | |
// Disclaimer !! it does not find wether the graph contains a -ve cycle in general | |
boolean containsNegativeCycle() { | |
for(int u=st;u<V+st;u++) | |
for(Edge e : adj[u]) | |
if(distTo[u] != INF && distTo[u] + e.cost < distTo[e.v]) | |
return true; | |
return false; | |
} | |
// Sets true for all vertices which are rechable from any negative cycle or null otherwise | |
boolean[] reachableFromNegativeCycle() { | |
if(!containsNegativeCycle()) | |
return null; | |
else { | |
ArrayDeque<Integer> queue = new ArrayDeque<>(); | |
boolean cycleMarked[] = new boolean[V + st]; | |
for(int u=st;u<V+st;u++) | |
for(Edge e : adj[u]) | |
if(distTo[u] != INF && distTo[u] + e.cost < distTo[e.v] && !cycleMarked[u]) { | |
cycleMarked[u] = true; | |
queue.add(u); | |
} | |
while(!queue.isEmpty()) { | |
int u = queue.remove(); | |
for(Edge e : adj[u]) | |
if(!cycleMarked[e.v]) { | |
cycleMarked[e.v] = true; | |
queue.add(e.v); | |
} | |
} | |
return cycleMarked; | |
} | |
} | |
} | |
static class Treap { | |
/* | |
* Based on https://sites.google.com/site/indy256/algo/treap_set | |
* It is a max priority heap based treap | |
*/ | |
// static final long SEED = 226366815112524829L; | |
static class TreapNode { | |
int key , cnt , size ; | |
int priority; | |
TreapNode left , right; | |
TreapNode(int key , int priority) { | |
left = right = null; | |
this.key = key; | |
this.priority = priority; | |
cnt = 1; | |
size = 1; | |
} | |
@Override | |
public String toString() { | |
return String.format("[key = %d prio = %d cnt = %d sz = %d]", | |
key , priority , cnt , size); | |
} | |
} | |
static class TreapNodePair { | |
TreapNode left , right; | |
TreapNodePair(TreapNode left , TreapNode right) { | |
this.left = left; | |
this.right = right; | |
} | |
} | |
private static int size(TreapNode treap) { | |
return treap == null ? 0 : treap.size; | |
} | |
private static void update(TreapNode treap) { | |
treap.size = treap.cnt + size(treap.left) + size(treap.right); | |
} | |
private Random rand; | |
private TreapNode root; | |
Treap() { | |
rand = new Random(); | |
root = null; | |
} | |
/* | |
* All the elements in the left tree are <= x | |
*/ | |
private TreapNodePair split(TreapNode treap , int x) { | |
if(treap == null) | |
return new TreapNodePair(null, null); | |
else if(treap.key <= x) { // No need to take care of left subtree now | |
TreapNodePair rightSplit = split(treap.right, x); | |
treap.right = rightSplit.left; | |
update(treap); | |
rightSplit.left = treap; | |
return rightSplit; | |
} | |
else { | |
TreapNodePair leftSplit = split(treap.left, x); | |
treap.left = leftSplit.right; | |
update(treap); | |
leftSplit.right = treap; | |
return leftSplit; | |
} | |
} | |
private TreapNode merge(TreapNode leftTreap , TreapNode rightTreap) { | |
if(leftTreap == null && rightTreap == null) | |
return null; | |
else if(leftTreap == null) | |
return rightTreap; | |
else if(rightTreap == null) | |
return leftTreap; | |
else { | |
if(leftTreap.priority > rightTreap.priority) { | |
leftTreap.right = merge(leftTreap.right, rightTreap); | |
update(leftTreap); | |
return leftTreap; | |
} | |
else { | |
rightTreap.left = merge(leftTreap , rightTreap.left); | |
update(rightTreap); | |
return rightTreap; | |
} | |
} | |
} | |
/* | |
* Increases the frequency of the key if found and returns true else false | |
*/ | |
private boolean increaseIfFound(TreapNode treap , int x) { | |
if(treap == null) | |
return false; | |
else if(x > treap.key && increaseIfFound(treap.right, x)) { | |
treap.size++; | |
return true; | |
} else if (x < treap.key && increaseIfFound(treap.left, x)) { | |
treap.size++; | |
return true; | |
} else if (x == treap.key) { | |
treap.cnt++; | |
treap.size++; | |
return true; | |
} else | |
return false; | |
} | |
private TreapNode insert(TreapNode treap , int x) { | |
if(treap == null) | |
return new TreapNode(x, rand.nextInt()); | |
else if(!increaseIfFound(treap, x)) { | |
TreapNodePair split = split(treap, x); | |
TreapNode newNode = merge(merge(split.left, new TreapNode(x, rand.nextInt())), split.right); | |
return newNode; | |
} | |
else | |
return treap; | |
} | |
public void insert(int x) { | |
root = insert(root, x); | |
} | |
private int getFrequency(TreapNode treap , int x) { | |
return treap == null ? 0 : | |
x < treap.key ? getFrequency(treap.left, x) : | |
x > treap.key ? getFrequency(treap.right, x) : | |
treap.cnt; | |
} | |
public int getFrequency(int x) { | |
return getFrequency(root, x); | |
} | |
private TreapNode remove(TreapNode treap , int x) { | |
if(treap == null) | |
return null; | |
else if(x < treap.key) { | |
treap.left = remove(treap.left, x); | |
update(treap); | |
return treap; | |
} | |
else if(x > treap.key) { | |
treap.right = remove(treap.right, x); | |
update(treap); | |
return treap; | |
} | |
else { | |
if(treap.cnt > 1) { | |
treap.cnt--; | |
treap.size--; | |
} | |
else | |
treap = merge(treap.left, treap.right); | |
return treap; | |
} | |
} | |
public void remove(int x) { | |
root = remove(root, x); | |
} | |
/* | |
* Counts the numbers less than or equal to x | |
*/ | |
private int countLess(TreapNode treap , int x) { | |
return treap == null ? 0 : | |
x < treap.key ? countLess(treap.left, x) : | |
x > treap.key ? size(treap.left) + treap.cnt + countLess(treap.right, x) : | |
size(treap.left) + treap.cnt; | |
} | |
public int countLess(int x) { | |
return countLess(root , x); | |
} | |
/* | |
* Counts the numbers greater than or equal to x | |
*/ | |
private int countGreater(TreapNode treap , int x) { | |
return treap == null ? 0 : | |
x < treap.key ? countGreater(treap.left, x) + treap.cnt + size(treap.right): | |
x > treap.key ? countGreater(treap.right, x) : | |
size(treap.right) + treap.cnt; | |
} | |
public int countGreater(int x) { | |
return countGreater(root , x); | |
} | |
private StringBuilder toString(StringBuilder prefix, boolean isTail, StringBuilder sb, TreapNode treap) { | |
if (treap == null) { | |
sb.append("Tree Empty\n"); | |
return sb; | |
} | |
if (treap.right != null) { | |
toString(new StringBuilder().append(prefix).append(isTail ? "│ " : " "), false, sb, treap.right); | |
} | |
sb.append(prefix).append(isTail ? "└── " : "┌── ").append(treap).append("\n"); | |
if (treap.left != null) { | |
toString(new StringBuilder().append(prefix).append(isTail ? " " : "│ "), true, sb, treap.left); | |
} | |
return sb; | |
} | |
@Override | |
public String toString() { | |
return this.toString(new StringBuilder(), true, new StringBuilder(), root).toString(); | |
} | |
} | |
// General impl http://codeforces.com/contest/858/submission/32363725 | |
static class BinaryTrie { | |
static class Node { | |
int size; | |
Node zero; | |
Node one; | |
Node() { | |
size = 1; // Take this into consideration | |
} | |
} | |
Node root; | |
static final int offset = 27; //Maximum index of set bit | |
BinaryTrie(){ | |
root = new Node(); | |
} | |
void insert(int num){ | |
root = insert(root, num, offset); | |
} | |
int size(Node n) { | |
return n == null ? 0 : n.size; | |
} | |
Node insert(Node curr , int num , int idx){ | |
if(idx < 0) { | |
if(curr != null) | |
curr.size++; | |
else | |
curr = new Node(); | |
return curr; | |
} | |
else{ | |
if(curr == null) | |
curr = new Node(); | |
if((num & (1 << idx)) == 0) | |
curr.zero = insert(curr.zero, num, idx - 1); | |
else | |
curr.one = insert(curr.one, num, idx - 1); | |
curr.size = size(curr.zero) + size(curr.one); | |
return curr; | |
} | |
} | |
void remove(int num){ | |
remove(root, null, num, offset); | |
} | |
void remove(Node curr , Node parent , int num , int idx){ | |
if(idx >= 0){ | |
if((num & (1 << idx)) == 0) | |
remove(curr.zero, curr, num, idx - 1); | |
else | |
remove(curr.one, curr, num, idx - 1); | |
} | |
curr.size--; | |
} | |
} | |
static int[] KMPPrefixFunction(char str[]) { | |
int n = str.length; | |
int prefix[] = new int[n]; // Stores the length of largest border for a prefix | |
for(int i = 1; i < n; i++) { | |
int border; | |
for(border = prefix[i - 1]; border > 0 && str[border] != str[i]; border = prefix[border - 1]) | |
; | |
prefix[i] = str[i] == str[border] ? border + 1: 0; | |
} | |
return prefix; | |
} | |
// Courtesy : UWI ( adjacency list using Jagged Arrays ) | |
static int[][] packU(int n, int[] from, int[] to , int isOneBased) { | |
int[][] g = new int[n + isOneBased][]; | |
int[] p = new int[n + isOneBased]; | |
for (int f : from) | |
p[f]++; | |
for (int t : to) | |
p[t]++; | |
for (int i = 0 + isOneBased; i < n + isOneBased; i++) | |
g[i] = new int[p[i]]; | |
for (int i = 0; i < from.length; i++) { | |
g[from[i]][--p[from[i]]] = to[i]; | |
g[to[i]][--p[to[i]]] = from[i]; | |
} | |
return g; | |
} | |
// Courtesy : UWI ( adjacency list using Jagged Arrays ) | |
static int[][] packD(int n, int[] from, int[] to , int isOneBased) { | |
int[][] g = new int[n + isOneBased][]; | |
int[] p = new int[n + isOneBased]; | |
for (int f : from) | |
p[f]++; | |
for (int i = 0 + isOneBased; i < n + isOneBased; i++) | |
g[i] = new int[p[i]]; | |
for (int i = 0; i < from.length; i++) | |
g[from[i]][--p[from[i]]] = to[i]; | |
return g; | |
} | |
static final double EPS = 1e-8; | |
static int compare(double a , double b) { | |
return a <= b - EPS ? -1 : a >= b + EPS ? 1 : 0; | |
} | |
static class Line implements Comparable<Line> { | |
int sNum , sDen , yInNum , yInDen; | |
int x; // for lines parallel to y axis | |
static int gcd(int a , int b) { return (b == 0) ? a : gcd(b, a % b); } | |
Line(int x1 , int y1 , int x2 , int y2) { | |
sNum = y2 - y1; | |
sDen = x2 - x1; | |
yInNum = y1 * x2 - x1 * y2; | |
yInDen = x2 - x1; | |
// System.out.println("before " + xInNum + " / " + xInDen + " " + yInNum + " / " + yInDen); | |
int g1 = gcd(sNum, sDen); | |
if(g1 != 0) { | |
sNum /= g1; | |
sDen /= g1; | |
} | |
int g2 = gcd(yInNum, yInDen); | |
if(g2 != 0) { | |
yInNum /= g2; | |
yInDen /= g2; | |
} | |
if(sDen == 0 && yInDen == 0) | |
x = x1; | |
} | |
@Override | |
public boolean equals(Object obj) { | |
Line other = (Line) obj; | |
return sDen == other.sDen && sNum == other.sNum && | |
yInDen == other.yInDen && yInNum == other.yInNum && x == other.x; | |
} | |
@Override | |
public int hashCode() { | |
return Objects.hash(sNum , sDen , yInNum , yInDen , x); | |
} | |
@Override | |
public int compareTo(Line o) { | |
if(sNum != o.sNum) | |
return sNum - o.sNum; | |
else if(sDen != o.sDen) | |
return sDen - o.sDen; | |
else if(yInNum != o.yInNum) | |
return yInNum - o.yInNum; | |
else if(yInDen != o.yInDen) | |
return yInDen - o.yInDen; | |
else if(x != o.x) | |
return x - o.x; | |
else | |
return 0; | |
} | |
@Override | |
public String toString() { | |
return sNum + " / " + sDen + " " + yInNum + " / " + yInDen + " x = " + x; | |
} | |
} | |
static class Rational { | |
static int gcd(int a , int b) { return (b == 0) ? a : gcd(b, a % b); } | |
int num , den; | |
Rational(int a , int b) { | |
int g = gcd(a, b); | |
num = a / g; | |
den = b / g; | |
} | |
@Override | |
public boolean equals(Object obj) { | |
Rational other = (Rational) obj; | |
return other.num == num && other.den == den; | |
} | |
@Override | |
public int hashCode() { | |
return Objects.hash(num , den); | |
} | |
@Override | |
public String toString() { | |
return "[" + num + " / " + den + "]"; | |
} | |
} | |
static class StringHashUtilsInt { | |
static final int p1 = 100151 , m1 = (int) 1e9 + 7; // Twin Primes | |
static final int p2 = p1 + 2 , m2 = m1 + 2; | |
static final int MAX = (int) 6e3 + 10; | |
static final int pow1[] = new int[MAX + 1]; | |
static final int pow2[] = new int[MAX + 1]; | |
static int modPow(long a , long b , long mod) { | |
long pow = 1; | |
while(b > 0) { | |
if((b & 1L) == 1) | |
pow = ((pow * a) % mod); | |
a = ((a * a) % (mod)); | |
b >>= 1; | |
} | |
return (int) pow; | |
} | |
static int modInverse(long n , long mod) {return modPow(n, mod - 2 , mod);} // Fermat's little theorem | |
static { | |
pow1[0] = pow2[0] = 1; | |
for(int i = 1; i <= MAX; i++) { | |
pow1[i] = (int) ((1L * pow1[i - 1] * p1) % (long)(m1)); | |
pow2[i] = (int) ((1L * pow2[i - 1] * p2) % (long)(m2)); | |
} | |
} | |
static int hash1[] , hash2[]; | |
static int cache1[] , cache2[]; | |
static int[] subHash(int l , int r) { | |
// l , r are 0 indexed | |
l++; | |
r++; | |
if(l > r) | |
return new int[] { 0 , 0 }; | |
return new int[] { | |
(int) ((1L * cache1[l - 1] * ((hash1[r] - hash1[l - 1] + m1) % m1)) % (long)(m1)), | |
(int) ((1L * cache2[l - 1] * ((hash2[r] - hash2[l - 1] + m2) % m2)) % (long)(m2)) | |
}; | |
} | |
public StringHashUtilsInt(String s) { | |
char str[] = s.toCharArray(); | |
int n = str.length; | |
hash1 = new int[n + 1]; | |
hash2 = new int[n + 1]; | |
cache1 = new int[n + 1]; | |
cache2 = new int[n + 1]; | |
hash1[1] = hash2[1] = str[0]; | |
for(int i = 2; i <= n; i++) { | |
hash1[i] = (hash1[i - 1] + ((int) ((1L * pow1[i - 1] * str[i - 1]) % (long)(m1)))) % m1; | |
hash2[i] = (hash2[i - 1] + ((int) ((1L * pow2[i - 1] * str[i - 1]) % (long)(m2)))) % m2; | |
} | |
for(int i = 0; i < n; i++) { | |
cache1[i] = modInverse(pow1[i], m1); | |
cache2[i] = modInverse(pow2[i], m2); | |
} | |
} | |
} | |
static class StringHashUtilsLong { | |
static final long p = 100151; | |
static final int MAX = (int) 5e3 + 10; | |
static final long pow[] = new long[MAX + 1]; | |
// implicit mod (2^63) | |
static { | |
pow[0] = 1; | |
for(int i = 1; i <= MAX; i++) | |
pow[i] = pow[i - 1] * p; | |
} | |
static long hash[]; | |
static long subHash(int l , int r) { | |
// l , r are 0 indexed | |
l++; | |
r++; | |
return hash[r] - hash[l - 1] * pow[r - l + 1]; | |
} | |
public StringHashUtilsLong(char str[]) { | |
int n = str.length; | |
hash = new long[n + 1]; | |
hash[1] = str[0]; | |
for(int i = 2; i <= n; i++) | |
hash[i] = hash[i - 1] * p + str[i - 1]; | |
} | |
} | |
/* | |
// Debug Array | |
static void pa(int a[]) { | |
Arrays.stream(a).forEach(i -> print(String.format("%3d ", i))); | |
print('\n'); | |
IntStream.range(0, a.length).forEach(i -> print(String.format("%3d ", i))); | |
print('\n'); | |
} | |
*/ | |
static class ExtendedEuclid { | |
// For comments please refer to uva 10090 | |
/* | |
* If the Linear Diophantine Equation is | |
* ax + by = c --- (1) | |
* then we denote the canonical equation of 1 as | |
* ax + by = d --- (2) , where d = gcd(a , b) | |
* using extended Euclid algorithm we get the solution for 2 as (x0 , y0) | |
* | |
* Now the general solution for 1 is given by | |
* x" = (x0 * c + t * b) / d | |
* y" = (y0 * c - t * a) / d | |
* | |
*/ | |
static long gcd(long a , long b) { return (b == 0) ? a : gcd(b, a % b); } | |
static long[] extendedEuclid(long a , long b) { | |
long rnm2[] = new long[]{0 , 1}; // r_n-2 , x , y | |
long rnm1[] = new long[]{1 , 0}; // r_n-1 , u , v | |
while(a != 0) { | |
long r = ((b % a) + a) % a; | |
long q = Long.signum(a) * Long.signum(b) < 0 && b % a != 0 ? b / a - 1 : b / a; | |
long coeffA = rnm2[0] - q * rnm1[0]; | |
long coeffB = rnm2[1] - q * rnm1[1]; | |
b = a; | |
a = r; | |
rnm2[0] = rnm1[0]; | |
rnm2[1] = rnm1[1]; | |
rnm1[0] = coeffA; | |
rnm1[1] = coeffB; | |
} | |
return new long[]{rnm2[0], rnm2[1] , b}; | |
} | |
// greater than a / b | |
static long grt(long a , long b) { | |
return (a / b) + (Long.signum(a) * Long.signum(b) < 0 && a % b != 0 ? 0 : 1); | |
} | |
// less than a / b | |
static long less(long a , long b) { | |
return (a / b) + (Long.signum(a) * Long.signum(b) > 0 && a % b != 0 ? 0 : -1); | |
} | |
// greater than equal to a / b | |
static long grtEq(long a , long b) { | |
return (a / b) + (Long.signum(a) * Long.signum(b) > 0 && a % b != 0 ? 1 : 0); | |
} | |
// less than or equal to a / b | |
static long lessEq(long a , long b) { | |
return (a / b) + (Long.signum(a) * Long.signum(b) < 0 && a % b != 0 ? -1 : 0); | |
} | |
} | |
static int[] compress(int arr[]) { | |
HashMap<Integer , Integer> map = new HashMap<>(); | |
for(int i = 1; i < arr.length; i++) | |
map.putIfAbsent(arr[i], map.size()); | |
// System.out.println(map); | |
int inv[] = new int[map.size()]; | |
for(int i = 1; i < arr.length; i++) { | |
inv[map.get(arr[i])] = arr[i]; | |
arr[i] = map.get(arr[i]); | |
} | |
return inv; | |
} | |
static double pt[][]; // array of coordinates | |
static double areaOfTri(int a , int b , int c) { | |
double t1 = pt[a][0] * (pt[b][1] - pt[c][1]); | |
double t2 = pt[b][0] * (pt[c][1] - pt[a][1]); | |
double t3 = pt[c][0] * (pt[a][1] - pt[b][1]); | |
return Math.abs((t1 + t2 + t3) / 2.0); | |
} | |
static double areaOfPoly(int start , int end) { | |
double area = 0; | |
int prev = end; | |
for(int i = start; i <= end; i++) { | |
area += (pt[prev][0] + pt[i][0]) * (pt[prev][1] - pt[i][1]); | |
prev = i; | |
} | |
return Math.abs(area / 2.0); | |
} | |
/* Used to get count of distinct elements in a range . | |
* “Next” array stores the next index such that arr[next[i]] == arr[i] . | |
* “last” stores the last index from end which has the particular value. | |
*/ | |
static class SegTreeNode { | |
int size; | |
SegTreeNode left, right; | |
public SegTreeNode(int size) { | |
this.size = size; | |
} | |
@Override | |
public String toString() { | |
return String.format("[sz = %d]", size); | |
} | |
} | |
static SegTreeNode persistent[]; | |
static int last[]; | |
static SegTreeNode initSegTree(int L, int R , int arr[]) { | |
if (L == R) | |
return new SegTreeNode(last[arr[L]] == L ? 1 : 0); | |
else { | |
SegTreeNode newNode = new SegTreeNode(0); | |
int mid = (L + R) >> 1; | |
newNode.left = initSegTree(L, mid , arr); | |
newNode.right = initSegTree(mid + 1, R , arr); | |
newNode.size = newNode.left.size + newNode.right.size; | |
return newNode; | |
} | |
} | |
static SegTreeNode initSegTree(SegTreeNode prev, int L, int R, int index, int val) { | |
if (L == R) | |
return new SegTreeNode(val); | |
else { | |
int mid = (L + R) >> 1; | |
SegTreeNode l = prev.left; | |
SegTreeNode r = prev.right; | |
if (index <= mid) | |
l = initSegTree(prev.left, L, mid, index, val); | |
else | |
r = initSegTree(prev.right, mid + 1, R, index, val); | |
SegTreeNode newNode = new SegTreeNode(l.size + r.size); | |
newNode.left = l; | |
newNode.right = r; | |
return newNode; | |
} | |
} | |
// Usage of Persistent Segment Tree | |
/* | |
Arrays.fill(last, n); | |
for(int i = n - 1; i >= 0; i--) { | |
next[i] = last[arr[i]]; | |
last[arr[i]] = i; | |
} | |
persistent = new SegTreeNode[n]; | |
persistent[0] = initSegTree(0, n - 1); | |
for(int i = 1; i < n - 1; i++) { | |
persistent[i] = initSegTree(persistent[i - 1], 0, n - 1, i - 1, 0); | |
if(next[i - 1] < n) | |
persistent[i] = initSegTree(persistent[i], 0, n - 1, next[i - 1], 1); | |
} | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment