Range max sum query using sparse table - c++

I Implemented range max sum query using sparse Table ,I Know more efficient approach would be using segment trees.
What I have tried:
I am calculating the max sum in the range (i,2^j-1) for all possible value of i and j and storing them in a table
where i is the index and j denotes the power of 2 (2^j denotes the length of segment from i for which we are calculating max sum)
Now using the above table we can answer the queries
Input:
3
-1 2 3
1
1 2
expected output:
2
actual output:
"wrong answer(garbage value)"
we actually have to tell the max contiguous sum in a given query
Link to the ques spoj gss1
Please help:
#include<iostream>
#include<vector>
#include<algorithm>
#include<climits>
using namespace std;
const int k = 16;
const int N = 1e5;
const int ZERO = 0; // ZERO + x = x + ZERO = x (for any x)
long long table[N][k + 1]; // k + 1 because we need to access table[r][k]
long long Arr[N];
int main()
{
int n, L, R, q;
cin >> n; // array size
for(int i = 0; i < n; i++)
cin >> Arr[i];
// build Sparse Table
for(int i = 0; i < n; i++)
table[i][0] = Arr[i];
for(int j = 1; j <= k; j++) {
for(int i = 0; i <= n - (1 << j); i++)
//table[i][j] = table[i][j - 1] + table[i + (1 << (j - 1))][j - 1];
table[i][j] = max(table[i][j-1],max(table[i+(1<<(j-1))][j-1],table[i+(1<<(j-1))][j-1]+table[i][j-1]));
}
cin >> q; // number of queries
for(int i = 0; i < q; i++) {
cin >> L >> R; // boundaries of next query, 0-indexed
long long int answer = LLONG_MIN;
for(int j = k; j >= 0; j--) {
if(L + (1 << j) - 1 <= R) {
answer = max(answer,answer + table[L][j]);
L += 1 << j; // instead of having L', we increment L directly
}
}
cout << answer << endl;
}
return 0;
}
link to the question Spoj Gss1

Related

Finding largest value in every array's column

Currently I have a 2D array and I need to find largest value of every array's column and find their sum.
My code seems to not work properly because I'm getting largest values of every row, not column, also the program sometimes prints the same value two times.
I wrote this code based on a tutorial and I don't know where I made a mistake. There should be basic C++ functions (cycles, if statements, arrays).
My code:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n, m, a[10][10], sum = 0, max;
cin >> n >> m;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> a[j][i];
}
}
for (int i = 0; i < m; i++) {
max = a[0][i];
for (int j = 0; j < n; j = j + 1) {
if (a[j][i] >= max) {
max = a[j][i];
sum = sum + a[j][i];
cout << max << endl; //control printing to see the values
}
}
}
cout << sum;
}
Input:
3 3
3 2 3
7 5 1
6 3 5
Output I need to get is 17 but I am getting 19 right now.
Assuming your array has m columns and n rows.
int sum = 0, max = 0;
for( int i = 0 ; i < m ; ++i )
{
max = 0;
for( int j = 0 ; j < n ; ++j )
{
if(max < a [j][i])
{
max = a[j][i];
}
}
sum += max;
}

How to solve the brute-force problem using associative container?

count the number of (a,b,c)(1≤a,b,c≤n) satisfying a^k+b^k=c^k (2≤ k ≤ 20)
How can I solve this problem by first restore all the result of a^k + b^k and then match c^k accordingly?
When I enter n = 10, the count will be 876, why will that happen?
#include<iostream>
#include<cmath>
#include<map>
#include<set>
using namespace std;
int main()
{
int n;
cin >> n;
int count = 0;
map<int, set<int> > hash;
for(int k = 2; k <= 20; ++k)
{
set<int> s;
hash[k] = s;
}
for(int c = 1; c <= n; ++c)
for(int k = 2; k <= 20; ++k)
hash[k].insert(pow(c,k));
for(int k = 2; k <= 20; ++k)
cout << "k=" << k << " -- " << hash[k].size() << endl;
for(int k = 2; k <= 20; ++k)
{
for(int a = 1; a <= n; ++a)
for(int b = 1; b <= n; ++b)
{
if(hash[k].find(pow(a,k) + pow(b,k)) != hash[k].end())
count++;
}
}
cout << count << endl;
return 0;
}
There exists no solution for a^k+b^k=c^k for k>2.
From Wikipedia:-
In number theory Fermat's Last Theorem states that no three positive integers a, b, and c satisfy the equation a^n + b^n = c^n for any integer value of n greater than 2.
The cases n = 1 and n = 2 have been known to have infinitely many solutions since antiquity
This also been proved.
So you can try to solve just for the value of k=2.
For k=2 You can use this link

Generating all R-digit numbers among N digits in C++ (combinations, iterative)?

I have a program, where I have to generate all R-digit numbers among N digits in C++, for example for N=3 (all digits from 1 to N inclusive) and R=2 the program should generate 12 13 21 23 31 32. I tried to do this with arrays as follows, but it does not seem to work correctly.
#define nmax 20
#include <iostream>
using namespace std;
int n, r;
void print(int[]);
int main()
{
cin >> n;
cin >> r;
int a[nmax];
int b[nmax];
int used[nmax];
for (int p = 1; p <= n; p++) {
//Filling the a[] array with numbers from 1 to n
a[p] = n;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < r; j++) {
b[j] = a[i];
used[j] = 1;
if (used[j]) {
b[j] = a[i + 1];
}
used[j] = 0;
}
print(b);
}
return 0;
}
void print(int k[]) {
for (int i = 0; i < r; i++) {
cout << k[i];
}
}
If I understand your question correctly, you can explore this website where it explains the problem and suggests the solution thoroughly.
Here is a slightly altered code:
Pay attention that time is an issue for bigger N values.
#define N 5 // number of elements to permute. Let N > 2
#include <iostream>
using namespace std;
// NOTICE: Original Copyright 1991-2010, Phillip Paul Fuchs
void PrintPerm(unsigned int *a, unsigned int j, unsigned int i){
for(unsigned int x = 0; x < N; x++)
cout << " " << a[x];
cout << " swapped( " << j << " , " << i << " )\n";
}
void QuickPerm(void){
unsigned int a[N], p[N+1];
register unsigned int i, j, PermCounter = 1; // Upper Index i; Lower Index j
for(i = 0; i < N; i++){ // initialize arrays; a[N] can be any type
a[i] = i + 1; // a[i] value is not revealed and can be arbitrary
p[i] = i;
}
p[N] = N; // p[N] > 0 controls iteration and the index boundary for i
PrintPerm(a, 0, 0); // remove comment to PrintPerm array a[]
i = 1; // setup first swap points to be 1 and 0 respectively (i & j)
while(i < N){
p[i]--; // decrease index "weight" for i by one
j = i % 2 * p[i]; // IF i is odd then j = p[i] otherwise j = 0
swap(a[i], a[j]); // swap(a[j], a[i])
PrintPerm(a, j, i); // remove comment to PrintPerm target array a[]
PermCounter++;
i = 1; // reset index i to 1 (assumed)
while (!p[i]) { // while (p[i] == 0)
p[i] = i; // reset p[i] zero value
i++; // set new index value for i (increase by one)
} // while(!p[i])
} // while(i < N)
cout << "\n\n ---> " << PermCounter << " permutations. \n\n\n";
} // QuickPerm()
int main(){
QuickPerm();
} //main
Here is a list of the modified items from the original code.
N defined to be 5 instead of 12.
A Counter has been added for more informative result.
The original swap instructions reduced by using c++ standard libraries' swap() function.
The getch() has been removed.
The 'Display()' function has been renamed to be 'PrintPerm()'.
The printf() function has been replaced by cout.
Printing number of permutation has been added.

Output not correct for my C++ program

So, I have the following problem:
From the file tabl.in a number n will be read (n<=50).
After that a square array with n rows and n columns will be read; all the numbers in the array will be composed by a maximum of 2 digits each.
Shown in the file tabl.out, the modulo between the sum of numbers found on the second diagonal of the array and 10, if the sum is palindrome (true=1, false=0), and the arithmetic mean of elements situated below of the main diagonal.
Will be writing functions for:
reading the array
calculation of the operation sum of secondary diagonal%10
checking if the previous result it is palindrome
calculation of the arithmetic mean below main diagonal
Example:
tabl.in:
4
5 8 2 12
1 0 3 16
1 2 1 11
5 7 2 19
tabl.out:
2 1 3
where
(12+3+2+5)%10 = 22%10 = 2
22 is palindrome = 1
1+2+2+1+7+5 = 18, 18/6=3
My code so far is:
#include <fstream>
using namespace std;
ifstream fin("tabl.in");
ofstream fout("tabl.out");
void readn(int Arr[][51], int n) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
fin >> Arr[i][j];
}
int sumsec(int Arr[][51], int n) {
int s = 0;
float r;
for (int i = 1; i <= n; i++)
s = s + Arr[i][n - i + 1];
r = s % 10;
return r;
}
void pald(int Arr[][51], int n) {
int s = 0, pal = 0;
for (int i = 1; i < n; i++)
s = s + Arr[i][n - i + 1];
while (s != 0) {
pal = pal * 10 + s % 10;
s = s / 10;
}
if (pal == s)
fout << "1 ";
else
fout << "0 ";
}
int ambmd(int Arr[][51], int n) {
int s = 0, k;
float ame;
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= i - 1; j++) {
s = s + Arr[i][j];
k++;
}
}
ame = s / k;
return ame;
}
int main() {
int Arr[51][51], n;
float r, ame;
fin >> n;
readn(Arr, n);
r = sumsec(Arr, n);
fout << r << " ";
pald(Arr, n);
ame = ambmd(Arr, n);
fout << ame;
}
But I have an issue with the palindrome() function: my output file will have 2 0 3 written to it for the given array from the example, instead of 2 1 3. What am I doing wrong?
Your pald function would work, if you compute s the same way as you do in sumsec and if s would still contain the sum, after you compute pal.
In your case, while (s != 0) {...}, followed by if (pal == s) {...} could be re-written as if (pal == 0), which is clearly not the intended solution. Just save your sum before computing pal, then compare with the saved sum.
Also, change your loop condition for computing s to for (int i = 1; i <= n; i++).
int s = 0, pal = 0, sum = 0;
for (int i = 1; i <= n; i++)
s = s + Arr[i][n - i + 1];
sum = s;
while (s != 0) {
pal = pal * 10 + s % 10;
s = s / 10;
}
if (pal == sum)
fout << "1 ";
else
fout << "0 ";
You should also consider the various comments for code improvements, like not re-computing the sum in the pald function.

C++ Sub sequence Exercise

I was assigned a "project" where I should create a C++ program to find the largest possible sum of two sub sequences. The user inputs N (array length), K (length of each sub sequence) and N numbers representing the array. The two sub sequences can touch but can't override each other e.g. 1 5 20 20 20 15 10 1 1 1 should output 90 ((5+20+20)+(20+15_10)) and not 115 ((20+20+20)+(20+20+15)).
My code until now is:
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int N, K, MaxN;
cin >> N;
cin >> K;
int Pi[N];
MaxN = N - K + 1;
int Word[MaxN];
int MaxSum;
for(int nn=0; nn<N; nn++) {
cin >> Pi[nn];
}
for(int y=0;y<MaxN;y++) {
Word[y] = 0;
}
for(int j=0; j<MaxN; j++) {
for(int l=0; l<K; l++) {
Word[j] = Word[j] + Pi[j+l];
}
}
sort(Word, Word + MaxN);
MaxSum = Word[MaxN-2] + Word[MaxN-1];
cout << MaxSum;
return 0;
}
Which is correct only in the case where the 2 sub sequences don't interfere with each other e.g. in an array such as 2 4 15 12 10 1 1 20 4 10 which outputs 71.
Thank you all in advance.
This is solution:
precalculate prefixes and suffixes
iterate end of the first subarray
iterate begin of the second subarray, but start from the end of first sub. ar. + 1
we have sum of numbers on interval from 0 to *end* = prefix[end], but we are interested only in interval [end - k, k], so simply subtract prefix[end] - prefix[end - k - 1]
[0 .. end-k-1, end-k .. end]
The same approach for the second subarray: sum2 = suffix[begin] - suffix[begin + i + 1]
then compare with the previous answer
So we just brute-force all possible sub-arrays which not intersect and find the max their sum
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int N,K,MaxN;
cin >> N;
cin >> K;
int Pi[N];
MaxN=N-K+1;
int Word[MaxN];
int MaxSum;
for(int nn=0;nn<N;nn++){
cin >> Pi[nn];
}
int prefix[N];
int sufix[N];
for (int i = 0; i < N; i++) {
prefix[i] = sufix[i] = 0;
}
for (int i = 0; i < N; i++) {
if (i == 0)
prefix[i] = Pi[i];
else
prefix[i] = Pi[i] + prefix[i - 1];
}
for (int i = N - 1; i >= 0; i--) {
if (i == N - 1)
sufix[i] = Pi[i];
else
sufix[i] = Pi[i] + sufix[i + 1];
}
int ans = 0;
for (int i = K - 1; i < MaxN; i++) {
for (int j = i + 1; j < MaxN; j++) {
int x = prefix[i] - (i - K >= 0 ? prefix[i - K] : 0);
int y = sufix[j] - (j + K < N ? sufix[j + K] : 0);
ans = max(ans, x + y);
}
}
cout << ans;
return 0;
}