Solving a using Segment Tree - java

You are given a sequence A of N (N <= 50000) integers between -10000 and 10000. On this sequence you have to apply M (M <= 50000) operations:
modify the i-th element in the sequence or for given x y print max{Ai + Ai+1 + .. + Aj | x<=i<=j<=y }.
Problem Link
I am using Segment Tree for this but i am not getting the correct output , please Help me where i have committed the mistake
CODE:
Making a Tree:
public static void maketree(int current , int a , int b ,int[] arr){
if(b<a) return;
if(b==a) {dp[current] = arr[a]; return ;}
maketree(2*current, a, (a+b)/2, arr);
maketree(2*current+1,1+ (a+b)/2, b, arr);
if(dp[2*current]>0 && dp[2*current+1]>0) dp[current] = dp[2*current] + dp[2*current+1];
else if(dp[2*current]>dp[2*current+1]) dp[current] = dp[2*current];
else dp[current] = dp[2*current+1];
}
Updating Function
public static void update(int current , int a , int b , int c , int value){
if(a>b || c<a || c>b) return ;
if(a==b){ dp[current] = value; return ; }
update(2*current, a, (a+b)/2, c, value);
update(2*current+1, (b+a)/2 +1, b, c, value);
if(dp[2*current]>0 && dp[2*current+1]>0) dp[current] = dp[2*current] + dp[2*current+1];
else if(dp[2*current]>dp[2*current+1]) dp[current] = dp[2*current];
else dp[current] = dp[2*current+1];
}
Query Function:
public static int query(int current , int a , int b , int i , int j){
int ans =0;
if(a>j || b<i || a>b) return Integer.MIN_VALUE;
if(a>=i && b<=j) return dp[current];
int x = query(2*current, a, (a+b)/2, i, j);
int y = query(2*current+1, (a+b)/2 +1, b, i, j);
if(x>0 && y>0) ans= x+y;
else if(x>y) ans = x;
else ans =y;
return ans;
}
I don;t know where i have made mistake please help , What will storage capacity required for dp array i.e. size of dp

when you are merging two nodes,then it may be like given below.execute any simple example so that you can feel it :)
void merge(node a , node b)
{
sum = a.sum + b.sum;
pre = max(a.pre , (a.sum + b.pre));
suf = max(b.suf , (b.sum + a.suf));
result = max(a.suf + b.pre,max(a.result , b.result));
}

it is quite overcomplicated imo...
int tree[1 << 17]; // 2 ^ 17 >= N * 2
int M = 1; //base of tree or sth i dont remember english name
int query(int L, int R){
int res = -10000; //minimum possible value in array
L += M - 1;
R += M - 1;
while(L <= R){
if(L % 2 == 1) res = max(res, tree[L++];
if(R % 2 == 0) res = max(res, tree[R++];
L /= 2;
R /= 2;
}
return res;
}
void update(int v, int value){
v += M - 1;
tree[v] = value;
while(v > 0){
v /= 2;
tree[v] = max(tree[v * 2], tree[v * 2 + 1]);
}
}
void make_tree(){
int n;
cin >> n;
while(M < n) M *= 2; // M is half of the size of tree
for(int i = 0;i < n;i++)
cin >> tree[i + M]; // just reading input to tree;
for(int i = M - 1;i > 0;i--) // first update for all nodes other than leafs
tree[i] = max(tree[i * 2], tree[i * 2 + 1]);
}

Related

Shortest path queries in a graph

We are given a static graph of N nodes, where we have edges as given below:
1. node-1 to node-i (for all 2 <= i <= N) of weight N + 1.
2. node-x to node-y (for all 2 <= x,y <= N) of weight 1, if and only if x divides y OR y divides x.
We are given Q queries of type(u, v) and we need to find shortest path between nodes u and v.
Constraints :
T <= 10^5 // number of test cases
N <= 2 * 10^5 // number of nodes
Q <= 2 * 10^5 // number of queries
u,v <= N
Approach : Almost constant time - O(1).
private int gcd(int x, int y) {
if(x % y == 0) return y;
return gcd(y, x % y);
}
private int lcm(int x, int y) {
return (x * y) / gcd(x, y);
}
private int[] shortest_path(int N, int Q, int[][] queries) {
int[] result = new int[Q];
int[] smallestDivisor = new int[N + 1];
for(int i = 2; i <= N; i++) {
if(smallestDivisor[i] == 0) {
int f = 1;
while(i * f <= N) {
if(smallestDivisor[i * f] == 0)
smallestDivisor[i*f] = i;
f += 1;
}
}
}
for(int i = 0; i < Q; i++) {
int u = queries[i][0];
int v = queries[i][1];
int LCM = lcm(u, v);
int GCD = gcd(u, v);
int smallestDivisorOfU = smallestDivisor[u];
int smallestDivisorOfV = smallestDivisor[v];
if(u == v)
result[i] = 0; // if nodes are same
else if(u == 1 || v == 1)
result[i] = N + 1; // if any of the node is '1'
else if(u % v == 0 || v % u == 0)
result[i] = 1; // if nodes are divisible
else if(GCD != 1 || LCM <= N)
result[i] = 2; // if gcd != 1 || lcm exists thus we can go as: 'x' --> gcd(x, y)/lcm(x,y) --> 'y' : 2 distance
else if(Math.min(smallestDivisorOfU * v, smallestDivisorOfV * u) <= N)
result[i] = 3;
else
result[i] = 2 * (N + 1); // we have to go via '1' node
}
return result;
}
Will this approach work for every test case?
Add GCD claculation before LCM to provide path A => GCD(A,B) => B (done)
When LCM checking fails, make factorization of values. If they are prime, move through "1" node. Otherwise check
if (min(SmallestDivisorOfA * B , SmallestDivisorOfB * A) <= N)
result[i] = 3;
Example: 7=>14=>2=>6

Pre-Increment (++i ) and i + 1 in Reccursions. Why do they have different action ? StackOverFlow Mistake

In the Recursion when I write res += countNatNum(++len, sum + i, k, d); I have a StackOverFlow mistake. But when I change pre-increment on len + 1 res res += countNatNum(len + 1, sum + i, k, d); everything is OK. I don't understand why does it happen because I check the condition with if (len == 3) ?
public static int countNatNum(int len, int sum, int k, int d){
int base = 9;
if (d > base * k) return 0;
else if (len == k){
if (sum == d){
return 1;
}
else return 0;
}
int res = 0;
int c = (len == 0 ? 1 : 0);
for (int i = c; i <= base; i++){
res += countNatNum(len + 1, sum + i, k, d);
}
return res;
}
}
The Program should count the number of natural numbers where sum of digits == another natural number. The program works correct but i don't understand why does pre-increment works in such strange way.
If you use "++" the updated value is stored again. ""len +1" on the other hand does not increment "len".

How to binary search in an array which is in an descending order?

my code doesn't work, I want to be able to binary search in an array which is in an descending order.
static int searchDescendingGT( double[] a, int i, int j, double x )
{
while(i!=j){
// | >x | unknown | >=x |
int m = i+(j-i)/2;
if (a[m]<x){
j = m;
}
else{
i = m+1;
}
}
return i;
}
What might be it's problems and what am I not seeing?
Try foll instead.
Assumption: a is your array, i = start, j= end, x is the element you're trying to find. Foll will return -1 if x not in a
static int searchDescendingGT(double[] a, int i, int j, double x) {
while (i <= j) {
int m = (i + j) / 2;
if (a[m] == x) {
return m;
} else if (a[m] < x) {
j = m - 1;
} else {
i = m + 1;
}
}
return -1;
}

Codility - Counting Elements Lessons : fastest algorithm swap

i am studying Codility chapter 2 : Counting elements.
I tried to make the exercise, and i think I have a good solution O(n). is It a valid solution ?
Is it a better solution that the BEST solution proposed in te lesson ?
Problem: You are given an integer m (1 􏰀 m 􏰀 1 000 000) and two non-empty, zero-indexed arrays A and B of n integers, a0,a1,...,an−1 and b0,b1,...,bn−1 respectively (0 􏰀 ai,bi 􏰀 m). The goal is to check whether there is a swap operation which can be performed on these arrays in such a way that the sum of elements in array A equals the sum of elements in array B after the swap. By swap operation we mean picking one element from array A and
one element from array B and exchanging them.
I tested my solution with these values :
int a[] = {2, 7, 12, 16};
int b[] = {4, 8, 9};
m = 16;
note: I commented the return to see the swapped values.
public int resultat(int[] A, int B[], int max) {
int sumA = Arrays.stream(A).sum();
int sumB = Arrays.stream(B).sum();
int[] countA = count(A, max);
int[] countB = count(B, max);
int diff = sumA - sumB;
int diffMin = 0;
if (diff % 2 != 0) {
return -1;
}
diffMin = diff / 2;
if (sumA > sumB) {
if (diff < countA.length && diffMin < countB.length && countA[diff] != 0 && countB[diffMin] != 0) {
System.out.println("A:" + diff + "- B:" + diffMin);
//return 1;
}
} else {
if (diffMin < countA.length && diff < countB.length && countB[diff] != 0 && countA[diffMin] != 0) {
System.out.println("A:" + diffMin + "- B:" + diff);
//return 1;
}
}
return -1;
}
public int[] count(int[] X, int max) {
int[] p = new int[max + 1];
Arrays.fill(p, 0);
for (int i = 0; i < X.length; i++) {
p[X[i]] += 1;
}
return p;
}
Your solution is O(n + m), because of count(A, max) and count(B, max) invocations. count() is linear.
It's not valid solution. Counter-example: A = [1, 2, 4], B = [3, 5, 1], m = 5. Answer is true, because we can swap 2 with 3. Your code throws ArrayIndexOutOfBoundsException: -2 on countB[diff], because diff is -2. Even if you secure it with, for example diff = Math.abs(sumA - sumB), the algorithm is still not correct and it will return false.
You don't need to do Arrays.fill(p, 0), int default value is 0.
Instead of p[X[i]] += 1 you could write p[X[i]]++.
Here's (i hope) a correct solution.
Please note, that counting can still be put after checking dif is not an odd number to make performance higher.
Note, too, that listA and listB arrays are used as the value at zero place is never used. This is for better understanding, too. We don't need the occurrence of the value 0 but we need the occurrence of max value.
public boolean solution(int[] A, int[] B, int max) {
int[] listA = new int[max+1];
int[] listB = new int[max+1];
int listAsum =0;
int listBsum=0;
for(int i = 0; i<A.length; i++){
listA[A[i]]++;
listAsum +=A[i];
listBsum +=B[i];
}
int diff = listAsum - listBsum;
if(diff%2 == 1) return false;
diff /=2;
for(int i=0; i<A.length; i++){
if((B[i] - diff) >= 0 && (B[i]-diff) <= max && listA[(B[i]-diff)] > 0) return true;
}
return false;
}
public boolean solution(int[] A, int[] B, int max) {
int[] count = new int[max + 1];//count(A, max);
int sum_a = 0; //Arrays.stream(A).sum();
int sum_b = 0;//Arrays.stream(B).sum();
for (int i = 0; i < A.length; i++) {
count[A[i]]++;
sum_a += A[i];
sum_b += B[i];
}
int d = sum_b - sum_a;
if (d % 2 == 1) return false;
d /= 2;
for (int i = 0; i < A.length; i++) {
if ((B[i] - d) >= 0 && (B[i] - d) <= max && count[(B[i] - d)] > 0)
return true;
}
return false;
}
public int[] count(int[] X, int max) {
int[] p = new int[max + 1];
Arrays.fill(p, 0);
for (int i = 0; i < X.length; i++) {
p[X[i]]++;
}
return p;
}

Does my pseudocode make sense? [duplicate]

This question already has an answer here:
Can you quickly tell me if this pseudocode makes sense or not?
(1 answer)
Closed 9 years ago.
I believe my code is now foolproof. I will write up the pseudocode now. But I do have one question. Why does DRJava ask that I return something outside of my if statements? As you can see I wrote for ex: "return 1;" just because it asked. It will never return that value however. Can someone explain this to me?
public class assignment1question2test {
public static void main(String[] args) {
int[] a = new int[1];
int l = 0;
int r = a.length-1;
for(int i=0; i<=r; i++) {
a[i] = 1;
}
a[0] = 10;
for (int i=0; i<=r; i++) {
System.out.println(a[i]);
}
System.out.print(recursiveSearch(a,l,r));
}
public static int recursiveSearch (int[] a, int l, int r) {
int third1 = (r-l)/3 + l;
int third2 = third1*2 - l + 1;
if (r-l == 0) {
return l;
}
System.out.println("i will be checking compare from " + l + " to " + third1 + " and " + (third1 + 1) + " to " + third2);
int compareResult = compare(a,l,third1,third1 + 1, third2);
if(r-l == 1) {
if (compareResult == 1) {
return l;
}
else {
return r;
}
}
if (compareResult == 0) {
return recursiveSearch(a,third2 + 1, r);
}
if (compareResult == 1) {
return recursiveSearch(a,l,third1);
}
if (compareResult == -1) {
return recursiveSearch(a,third1 + 1, third2);
}
return 1;
}
public static int compare(int[] a, int i, int j, int k, int l) {
int count1 = 0;
int count2 = 0;
for(int g=i; g<=j; g++) {
count1 = count1 + a[g];
}
for(int g=k; g<=l; g++) {
count2 = count2 + a[g];
}
if (count1 == count2) {
return 0;
}
if (count1 > count2) {
return 1;
}
if (count1 < count2) {
return -1;
}
return 0;
}
}
FINAL PSEUDOCODE I THINK
Algorithm: recursiveSearch (a,l,r)
Inputs: An array a, indices l and r which delimit the part of interest.
Output: The index that has the lead coin.
int third1 ← (r - l)/3
int third2 ← third1*2 - l + 1
if (r-l = 0) then
return l
int compareResult ← compare(a,l,third1,third1 + 1,third2)
if (r-l = 1) then
if (compareResult = 1) then
return l
else
return r
if (compareResult = 0) then
return recursiveSearch(a, third2 + 1, r)
if (compareResult = "1") then
return recursiveSearch(a,l,third1)
if (compareResult = "-1") then
return recursiveSearch(a,third1 + 1,third2)
String compareResult ← compare(a,l,mid,mid,r)
Here you check the middle element twice, make it:
String compareResult ← compare(a,l,mid,mid+1,r)
Apart from that your algorithm seems fair enough to me.
You should refine you logic more, it doesn't consider the case where the number of coin is even.
Odd: take a coin out, divide the remaining into 2 equal half and do the comparison.
Even: divide the remaining into 2 equal half and do the comparison.
For recursive function, please also define the base case:
When n=1, return the coin.
When n=2, return the heavier coin.
NumberOfCoin = r-l+1
if (NumberOfCoin = 1)
return l;
if (NumberOfCoin = 2)
compare(a,l,l,r,r)
0: Think it yourself
-1: Think it yourself
1: Think it yourself
if (NumberOfCoin is odd number)
mid = Think it yourself
compare(a, l, mid-1, mid+1, r)
0: Think it yourself
-1: Think it yourself
1: Think it yourself
if (NumberOfCoin is even number)
mid = l+r/2
compare(a, l, mid, mid+1, r)
0: Think it yourself
-1: Think it yourself
1: Think it yourself

Categories