The problem:
In this task, you need to write a regular segment tree for the sum.
Input The first line contains two integers n and m (1≤n,m≤100000), the
size of the array and the number of operations. The next line contains
n numbers a_i, the initial state of the array (0≤a_i≤10^9). The following
lines contain the description of the operations. The description of
each operation is as follows:
1 i v: set the element with index i to v (0≤i<n, 0≤v≤10^9).
2 l r:
calculate the sum of elements with indices from l to r−1 (0≤l<r≤n).
Output
For each operation of the second type print the corresponding
sum.
I'm trying to implement segment tree and all my functions works properly except for the update function:
void update(int i, int delta, int v = 0, int tl = 0, int tr = n - 1)
{
if (tl == i && tr == i)
t[v] += delta;
else if (tl <= i && i <= tr)
{
t[v] += delta;
int m = (tl + tr) / 2;
int left = 2 * v + 1;
int right = left + 1;
update(i, delta, left, tl, m);
update(i, delta, right, m + 1, tr);
}
}
I got WA on segment tree problem, meanwhile with this update function I got accepted:
void update(int i, int new_value, int v = 0, int tl = 0, int tr = n - 1)
{
if (tl == i && tr == i)
t[v] = new_value;
else if (tl <= i && i <= tr)
{
int m = (tl + tr) / 2;
int left = 2 * v + 1;
int right = left + 1;
update(i, new_value, left, tl, m);
update(i, new_value, right, m + 1, tr);
t[v] = t[left] + t[right];
}
}
I really don't understand why my first version is not working. I thought maybe I had some kind of overflowing problem and decided to change everything to long longs, but it didn't help, so the problem in the algorithm of updating itself. But it seems ok to me. For every segment that includes i I need to add sum of this segment to some delta (it can be negative, if for example I had number 5 and decided to change it to 3, then delta will be -2). So what's the problem? I really don't see it :(
There are 2 problems with your first solution:
The question expects you to do a point update. The condition (tl == i && tr == i) checks if you are the leaf node of the tree.
At leaf node, you have to actually replace the value instead of adding something into it, which you did for the second solution.
Secondly, you can only update the non-leaf nodes after all its child nodes are updated. Updating t[v] before making recursive call will anyways result into wrong answer.
Related
Consider there are N houses on a single road. I have M lightpoles. Given that M < N. Distance between all adjacent houses are different. Lightpole can be placed at the house only. And I have to place all lightpoles at house so that sum of distances from each house to its nearest lightpole is smallest. How can I code this problem?
After a little research I came to know that I have to use dynamic programming for this problem. But I don't know how to approach it to this problem.
Here's a naive dynamic program with search space O(n^2 * m). Perhaps others know of another speedup? The recurrence should be clear from the function f in the code.
JavaScript code:
// We can calculate these in O(1)
// by using our prefixes (ps) and
// the formula for a subarray, (j, i),
// reaching for a pole at i:
//
// ps[i] - ps[j-1] - (A[i] - A[j-1]) * j
//
// Examples:
// A: [1,2,5,10]
// ps: [0,1,7,22]
// (2, 3) =>
// 22 - 1 - (10 - 2) * 2
// = 5
// = 10-5
// (1, 3) =>
// 22 - 0 - (10 - 1) * 1
// = 13
// = 10-5 + 10-2
function sumParts(A, j, i, isAssigned){
let result = 0
for (let k=j; k<=i; k++){
if (isAssigned)
result += Math.min(A[k] - A[j], A[i] - A[k])
else
result += A[k] - A[j]
}
return result
}
function f(A, ps, i, m, isAssigned){
if (m == 1 && isAssigned)
return ps[i]
const start = m - (isAssigned ? 2 : 1)
const _m = m - (isAssigned ? 1 : 0)
let result = Infinity
for (let j=start; j<i; j++)
result = Math.min(
result,
sumParts(A, j, i, isAssigned)
+ f(A, ps, j, _m, true)
)
return result
}
var A = [1, 2, 5, 10]
var m = 2
var ps = [0]
for (let i=1; i<A.length; i++)
ps[i] = ps[i-1] + (A[i] - A[i-1]) * i
var result = Math.min(
f(A, ps, A.length - 1, m, true),
f(A, ps, A.length - 1, m, false))
console.log(`A: ${ JSON.stringify(A) }`)
console.log(`ps: ${ JSON.stringify(ps) }`)
console.log(`m: ${ m }`)
console.log(`Result: ${ result }`)
I got you covered bud. I will write to explain the dynamic programming algorithm first and if you are not able to code it, let me know.
A-> array containing points so that A[i]-A[i-1] will be the distance between A[i] and A[i-1]. A[0] is the first point. When you are doing memoization top-down, you will have to handle cases when you would want to place a light pole at the current house or you would want to place it at a lower index. If you place it now, you recurse with one less light pole available and calculate the sum of distances with previous houses. You handle the base case when you are not left with any ligh pole or you are done with all the houses.
I'm building a heatmap-like rectangular array interface and I want the 'hot' location to be at the top left of the array, and the 'cold' location to be at the bottom right. Therefore, I need an array to be filled diagonally like this:
0 1 2 3
|----|----|----|----|
0 | 0 | 2 | 5 | 8 |
|----|----|----|----|
1 | 1 | 4 | 7 | 10 |
|----|----|----|----|
2 | 3 | 6 | 9 | 11 |
|----|----|----|----|
So actually, I need a function f(x,y) such that
f(0,0) = 0
f(2,1) = 7
f(1,2) = 6
f(3,2) = 11
(or, of course, a similar function f(n) where f(7) = 10, f(9) = 6, etc.).
Finally, yes, I know this question is similar to the ones asked here, here and here, but the solutions described there only traverse and don't fill a matrix.
Interesting problem if you are limited to go through the array row by row.
I divided the rectangle in three regions. The top left triangle, the bottom right triangle and the rhomboid in the middle.
For the top left triangle the values in the first column (x=0) can be calculated using the common arithmetic series 1 + 2 + 3 + .. + n = n*(n+1)/2. Fields in the that triangle with the same x+y value are in the same diagonal and there value is that sum from the first colum + x.
The same approach works for the bottom right triangle. But instead of x and y, w-x and h-y is used, where w is the width and h the height of rectangle. That value have to be subtracted from the highest value w*h-1 in the array.
There are two cases for the rhomboid in the middle. If the width of rectangle is greater than (or equal to) the height, then the bottom left field of the rectangle is the field with the lowest value in the rhomboid and can be calculated that sum from before for h-1. From there on you can imagine that the rhomboid is a rectangle with a x-value of x+y and a y-value of y from the original rectangle. So calculations of the remaining values in that new rectangle are easy.
In the other case when the height is greater than the width, then the field at x=w-1 and y=0 can be calculated using that arithmetic sum and the rhomboid can be imagined as a rectangle with x-value x and y-value y-(w-x-1).
The code can be optimised by precalculating values for example. I think there also is one formula for all that cases. Maybe i think about it later.
inline static int diagonalvalue(int x, int y, int w, int h) {
if (h > x+y+1 && w > x+y+1) {
// top/left triangle
return ((x+y)*(x+y+1)/2) + x;
} else if (y+x >= h && y+x >= w) {
// bottom/right triangle
return w*h - (((w-x-1)+(h-y-1))*((w-x-1)+(h-y-1)+1)/2) - (w-x-1) - 1;
}
// rhomboid in the middle
if (w >= h) {
return (h*(h+1)/2) + ((x+y+1)-h)*h - y - 1;
}
return (w*(w+1)/2) + ((x+y)-w)*w + x;
}
for (y=0; y<h; y++) {
for (x=0; x<w; x++) {
array[x][y] = diagonalvalue(x,y,w,h);
}
}
Of course if there is not such a limitation, something like that should be way faster:
n = w*h;
x = 0;
y = 0;
for (i=0; i<n; i++) {
array[x][y] = i;
if (y <= 0 || x+1 >= w) {
y = x+y+1;
if (y >= h) {
x = (y-h)+1;
y -= x;
} else {
x = 0;
}
} else {
x++;
y--;
}
}
What about this (having an NxN matrix):
count = 1;
for( int k = 0; k < 2*N-1; ++k ) {
int max_i = std::min(k,N-1);
int min_i = std::max(0,k-N+1);
for( int i = max_i, j = min_i; i >= min_i; --i, ++j ) {
M.at(i).at(j) = count++;
}
}
Follow the steps in the 3rd example -- this gives the indexes (in order to print out the slices) -- and just set the value with an incrementing counter:
int x[3][3];
int n = 3;
int pos = 1;
for (int slice = 0; slice < 2 * n - 1; ++slice) {
int z = slice < n ? 0 : slice - n + 1;
for (int j = z; j <= slice - z; ++j)
x[j][slice - j] = pos++;
}
At a M*N matrix, the values, when traversing like in your stated example, seem to increase by n, except for border cases, so
f(0,0)=0
f(1,0)=f(0,0)+2
f(2,0)=f(1,0)+3
...and so on up to f(N,0). Then
f(0,1)=1
f(0,2)=3
and then
f(m,n)=f(m-1,n)+N, where m,n are index variables
and
f(M,N)=f(M-1,N)+2, where M,N are the last indexes of the matrix
This is not conclusive, but it should give you something to work with. Note, that you only need the value of the preceding element in each row and a few starting values to begin.
If you want a simple function, you could use a recursive definition.
H = height
def get_point(x,y)
if x == 0
if y == 0
return 0
else
return get_point(y-1,0)+1
end
else
return get_point(x-1,y) + H
end
end
This takes advantage of the fact that any value is H+the value of the item to its left. If the item is already at the leftmost column, then you find the cell that is to its far upper right diagonal, and move left from there, and add 1.
This is a good chance to use dynamic programming, and "cache" or memoize the functions you've already accomplished.
If you want something "strictly" done by f(n), you could use the relationship:
n = ( n % W , n / H ) [integer division, with no remainder/decimal]
And work your function from there.
Alternatively, if you want a purely array-populating-by-rows method, with no recursion, you could follow these rules:
If you are on the first cell of the row, "remember" the item in the cell (R-1) (where R is your current row) of the first row, and add 1 to it.
Otherwise, simply add H to the cell you last computed (ie, the cell to your left).
Psuedo-Code: (Assuming array is indexed by arr[row,column])
arr[0,0] = 0
for R from 0 to H
if R > 0
arr[R,0] = arr[0,R-1] + 1
end
for C from 1 to W
arr[R,C] = arr[R,C-1]
end
end
I am having two numbers L and R, L means left and R means Right.
I have to get to a certain number(F) using L and R.
Every time i have to start with zero as initial.
Example :
L : 1
R : 2
F : 3
SO minimum number of steps needed to get to F is 3.
Ans : First R, Second R, Third L.
IN this way i need to find the minimum number of ways to do it.
My approach:
Quo = F/R;
Remain : F%R;
x*R-Y*L = Remain
==> (x*R - Remain)/L = Y
this equation is break when (x*R - Remain)%L = 0, so we find x and y from the equation above.
So final Steps would be Quo + x(No. of right steps) + y( no. of left steps).
For Above Example :
Quo = 3/2 = 1;
Remain = 3%2 =1;
Y = (x*2 -1)/1
(x*2 -1)%1 is zero for x=1;
Now increase x from zero,
So x is 1, y is 1
Final Ans = Quo (1) + x (1) + y(1) = 3.
My code :
#include <iostream>
using namespace std;
int main()
{
int F,R,L;
cin >> F;
cin >> R;
cin >> L;
int remain = F%R;
int quo = F/R;
int Right = 0;
int left = 0;
int mode = 1;
while( mode !=0)
{
Right++;
mode = (R*Right - remain)%L;
left = (R*Right - remain)/L;
}
int final = quo + Right + left;
cout << final;
}
But i Don't think it is the good approach as i am putting x in loop which can be pretty costly
Can you please suggest me a good approach to do this question ?
In the given below equation
x*R - Remain = 0modL
where R, L and Remain are fixed.
It can be written as
((x*R)mod L - Remain mod L) mod L = 0
If Remain mod L = 0, then x*R should be multiple of L which makes x to 0modL.
Means x can be 0, nR where n is Integer.
So, simply, you can try x between 0 and L-1 to find x.
So, your loop can run from 0 to L-1 which will keep your loop finite.
Please note that this mod is different from %. -1 mod L = L-1 whereas -1%L = -1
There is another approach.
x*R mod L - Remain mod L = 0 mod L
leads to
x*R mod L = Remain mod L
(x* (R mod L)) mod L = (Remain mod L)
You can compute inverse of R (say Rinv) in field of L (if it does exists) and compute x = (Remain*Rinv)modL.
If inverse does not exists, it means equation cannot be satisfied.
Note: I am not mathematical expert. So, please give your opinion if anything is wrong.
See: https://www.cs.cmu.edu/~adamchik/21-127/lectures/congruences_print.pdf
I'm trying to solve the following problem:
A rectangular paper sheet of M*N is to be cut down into squares such that:
The paper is cut along a line that is parallel to one of the sides of the paper.
The paper is cut such that the resultant dimensions are always integers.
The process stops when the paper can't be cut any further.
What is the minimum number of paper pieces cut such that all are squares?
Limits: 1 <= N <= 100 and 1 <= M <= 100.
Example: Let N=1 and M=2, then answer is 2 as the minimum number of squares that can be cut is 2 (the paper is cut horizontally along the smaller side in the middle).
My code:
cin >> n >> m;
int N = min(n,m);
int M = max(n,m);
int ans = 0;
while (N != M) {
ans++;
int x = M - N;
int y = N;
M = max(x, y);
N = min(x, y);
}
if (N == M && M != 0)
ans++;
But I am not getting what's wrong with this approach as it's giving me a wrong answer.
I think both the DP and greedy solutions are not optimal. Here is the counterexample for the DP solution:
Consider the rectangle of size 13 X 11. DP solution gives 8 as the answer. But the optimal solution has only 6 squares.
This thread has many counter examples: https://mathoverflow.net/questions/116382/tiling-a-rectangle-with-the-smallest-number-of-squares
Also, have a look at this for correct solution: http://int-e.eu/~bf3/squares/
I'd write this as a dynamic (recursive) program.
Write a function which tries to split the rectangle at some position. Call the function recursively for both parts. Try all possible splits and take the one with the minimum result.
The base case would be when both sides are equal, i.e. the input is already a square, in which case the result is 1.
function min_squares(m, n):
// base case:
if m == n: return 1
// minimum number of squares if you split vertically:
min_ver := min { min_squares(m, i) + min_squares(m, n-i) | i ∈ [1, n/2] }
// minimum number of squares if you split horizontally:
min_hor := min { min_squares(i, n) + min_squares(m-i, n) | i ∈ [1, m/2] }
return min { min_hor, min_ver }
To improve performance, you can cache the recursive results:
function min_squares(m, n):
// base case:
if m == n: return 1
// check if we already cached this
if cache contains (m, n):
return cache(m, n)
// minimum number of squares if you split vertically:
min_ver := min { min_squares(m, i) + min_squares(m, n-i) | i ∈ [1, n/2] }
// minimum number of squares if you split horizontally:
min_hor := min { min_squares(i, n) + min_squares(m-i, n) | i ∈ [1, m/2] }
// put in cache and return
result := min { min_hor, min_ver }
cache(m, n) := result
return result
In a concrete C++ implementation, you could use int cache[100][100] for the cache data structure since your input size is limited. Put it as a static local variable, so it will automatically be initialized with zeroes. Then interpret 0 as "not cached" (as it can't be the result of any inputs).
Possible C++ implementation: http://ideone.com/HbiFOH
The greedy algorithm is not optimal. On a 6x5 rectangle, it uses a 5x5 square and 5 1x1 squares. The optimal solution uses 2 3x3 squares and 3 2x2 squares.
To get an optimal solution, use dynamic programming. The brute-force recursive solution tries all possible horizontal and vertical first cuts, recursively cutting the two pieces optimally. By caching (memoizing) the value of the function for each input, we get a polynomial-time dynamic program (O(m n max(m, n))).
This problem can be solved using dynamic programming.
Assuming we have a rectangle with width is N and height is M.
if (N == M), so it is a square and nothing need to be done.
Otherwise, we can divide the rectangle into two other smaller one (N - x, M) and (x,M), so it can be solved recursively.
Similarly, we can also divide it into (N , M - x) and (N, x)
Pseudo code:
int[][]dp;
boolean[][]check;
int cutNeeded(int n, int m)
if(n == m)
return 1;
if(check[n][m])
return dp[n][m];
check[n][m] = true;
int result = n*m;
for(int i = 1; i <= n/2; i++)
int tmp = cutNeeded(n - i, m) + cutNeeded(i,m);
result = min(tmp, result);
for(int i = 1; i <= m/2; i++)
int tmp = cutNeeded(n , m - i) + cutNeeded(n,i);
result = min(tmp, result);
return dp[n][m] = result;
Here is a greedy impl. As #David mentioned it is not optimal and is completely wrong some cases so dynamic approach is the best (with caching).
def greedy(m, n):
if m == n:
return 1
if m < n:
m, n = n, m
cuts = 0
while n:
cuts += m/n
m, n = n, m % n
return cuts
print greedy(2, 7)
Here is DP attempt in python
import sys
def cache(f):
db = {}
def wrap(*args):
key = str(args)
if key not in db:
db[key] = f(*args)
return db[key]
return wrap
#cache
def squares(m, n):
if m == n:
return 1
xcuts = sys.maxint
ycuts = sys.maxint
x, y = 1, 1
while x * 2 <= n:
xcuts = min(xcuts, squares(m, x) + squares(m, n - x))
x += 1
while y * 2 <= m:
ycuts = min(ycuts, squares(y, n) + squares(m - y, n))
y += 1
return min(xcuts, ycuts)
This is essentially classic integer or 0-1 knapsack problem that can be solved using greedy or dynamic programming approach. You may refer to: Solving the Integer Knapsack
I am trying to solve SPOJ problem GSS1 (Can you answer these queries I) using segment tree. I am using 'init' method to initialise a tree and 'query' method to get maximum in a range [i,j].
Limits |A[i]| <= 15707 and 1<=N (Number of elements)<=50000.
int A[50500], tree[100500];
void init(int n, int b, int e) // n=1, b=lower, e=end
{
if(b == e)
{
tree[n] = A[b];
return;
}
init(2 * n, b, (b + e) / 2);
init(2 * n + 1, ((b + e) / 2) + 1, e);
tree[n] = (tree[2 * n] > tree[2 * n + 1]) ? tree[2 * n] : tree[2 * n + 1];
}
int query(int n, int b, int e, int i, int j) // n=1, b=lower, e=end, [i,j]=range
{
if(i>e || j<b)
return -20000;
if(b>=i && e<=j)
return tree[n];
int p1 = query(2 * n, b, (b + e) / 2, i, j);
int p2 = query(2 * n + 1, ((b + e) / 2) + 1, e, i, j);
return (p1 > p2) ? p1 : p2;
}
Program is giving Wrong Answer.I debbuged code for most of the cases (negative numbers, odd/even N) but I am unable to figure out what is wrong with algorithm.
If anyone can point me in right direction, I would be grateful.
Thanks
I fear the (accepted) answer has missed out on a very important point here. The problem is here with the algorithm used in the code itself. The code says the answer for the node is the max of its children's values. But it is very much possible that the maximum subarray lies partially in BOTH children. For example
-1 -2 3 4 5 6 -5 -10 (n=8)
The code will output 11 while the answer is 18.
You will need to look into this case also to beat WA.
(I am answering this because the accepted answer is not entirely right and doesn't answer this question correctly.)
Edit: it seems your implementation is also correct, I'm just having another. And we both misread the problem statement.
I guess you call your query function with params
query( 1, 0, n-1, x-1, y-1 );
I believe that it's wrong to handle with segment tree in such way when your n is not a pow of 2.
I'm offering you to
enlarge tree array to 131072 elements (2^17) and A to 65536 (2^16);
found the smallest k such is not smaller than n and is a pow of 2;
initialize elements from n (0-based) to k-1 with -20000;
make n equal to k;
make sure you call init(1,0,n-1);
Hope that'll help you to beat WA.