I have a question regarding already asked this question:
SPOJ DQUERY : TLE Even With BIT?
What if I would like to not consider the repeated element to count when I make a range query?
following is an example:
Input
Line 1: n (1 ≤ n ≤ 10^6).
Line 2: n numbers a1, a2, ..., an (-10^9 ≤ ai ≤ ).
Line 3: q (1 ≤ q ≤ 10^6), the number of d-queries.
In the next q lines, each line contains 2 numbers i, j
representing a d-query (1 ≤ i ≤ j ≤ n).
Output
For each d-query (i, j), print the number of distinct elements in the
subsequence ai, ai+1, ..., aj in a single line.
Example
Input
9
1 2 3 2 4 1 2 3 4
3
1 9
2 4
5 9
2 7
Output
0 //Explanation: all elements have been repeated.
1 //Explanation: only 3 has not repeated.
3 //Explanation: only 4 is repeated, so count only 1, 2 and 3.
3 //Explanation: only 2 is repeated, so count only 3, 4 and 1.
what could it be the necessary changes which should have done in #kraskevich 's answer(which is an efficient solution for that particular case)? I tried to add 0 in BIT, instead of -1 in above-mentioned solution, which does not help for all types of queries. Can anybody get me an idea?
I finally made it using MOs Algorithm. Following will work as expected.
/** For the given set of queries find the Unique element
* count of an array using MO's Algorithum. */
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <unordered_map>
using namespace std;
struct Query // struct for storing the queries
{
int Left;
int Right;
int Index;
};
inline void Add(const int i, int &ans, vector<int> &Arr, vector<int> &countArray)
{
++countArray[Arr[i]];
if(countArray[Arr[i]] == 1)
ans += countArray[Arr[i]];
if(countArray[Arr[i]] == 2)
ans -= countArray[Arr[i]];
}
inline void Remove(const int i, int &ans, vector<int> &Arr, vector<int> &countArray)
{
--countArray[Arr[i]];
if(countArray[Arr[i]] == 1)
ans += countArray[Arr[i]];
if(countArray[Arr[i]] == 0)
ans -= countArray[Arr[i]];
}
int main()
{
int _size; cin >> _size;
vector<int> Arr; Arr.reserve(_size);
copy_n(istream_iterator<int>(cin), _size, back_inserter(Arr));
//copy(Arr.cbegin(), Arr.cend(), ostream_iterator<int>(cout, "\t"));
int id = -1;
int sqrt_n = sqrt(_size);
int Q; cin >> Q;
vector<Query> qArr(Q);
unordered_map<int, int> Map;
for (int i = 0; i < _size; ++i)
{
if (Map.count(Arr[i]) == 0)
Map[Arr[i]] = ++id;
Arr[i] = Map[Arr[i]];
}
// read queries
for (int i = 0; i < Q; ++i)
{
int L,R;
cin >> L >> R;
qArr[i].Left = L-1;
qArr[i].Right = R-1;
qArr[i].Index = i;
}
// sort the queries according to(MO's Algorithum)
sort(qArr.begin(),qArr.end(),
[&](const Query &lhs, const Query &rhs)->bool
{
return ( (lhs.Left/sqrt_n == rhs.Left/sqrt_n) ?
lhs.Right < rhs.Right: // Qs with same Left case
(lhs.Left / sqrt_n) < (rhs.Left / sqrt_n) ); // Qs with diff values case
});
int currStart = 0;
int currEnd = 0;
int tempAnswer= 0;
vector<int> Answer(Q);
vector<int> countArray(_size);
for (int i = 0; i < Q; ++i)
{
int L = qArr[i].Left;
int R = qArr[i].Right;
/** Remove extra elements of previous range. For
* example if previous range is [0, 3] and current
* range is [2, 5], then a[0] and a[1] are subtracted */
while (currStart < L)
{
Remove(currStart, tempAnswer, Arr, countArray);
++currStart;
}
/** Add Elements of current Range */
while (currStart > L)
{
Add(currStart - 1, tempAnswer, Arr, countArray);
--currStart;
}
while (currEnd <= R)
{
Add(currEnd, tempAnswer, Arr, countArray);
++currEnd;
}
/** Remove elements of previous range. For example
* when previous range is [0, 10] and current range
* is [3, 8], then a[9] and a[10] are subtracted */
while (currEnd > R + 1)
{
Remove(currEnd - 1, tempAnswer, Arr, countArray);
--currEnd;
}
Answer[qArr[i].Index] = tempAnswer;
}
for(const auto &it: Answer) cout<<it<<endl;
return 0;
}
Related
this function prints all triplets in an array whose product is a number k
input first line number of elements, second array elements, third target product .. passes parameters to recursive function f along with a vector that stores elements whose product might give k
thought process -> for each element we can include or exclude it to get the product k. If p > 24 or number elements multiplied > 3 we backtrack. once the prod = k, we print all numbers from vector v and pop them out and set number of elements count to 0 and product to 1 and continue
for an input of:
9
1 2 3 12 4 7 5 24 9
24
my output looks something like this :
12
2
1
9
9
9
| ->cursor justs stops here ..no further outputs...
naming scheme used :
count -> number of elements multiplied till now whose product is stored in -> p
n-> number of elements in array
k -> target pdt
i -> index of element in array currently at
code :
#include <iostream>
#include <vector>
using namespace std;
// all triplets whose product is a number k
void f(int i, int count, int p, int k, vector<int>&v, int *a, int n)
{
// success condition
if(count == 3 && p == k)
{
for(int i = 2; i >= 0; --i)
{
cout << v[i] << " " << endl;
v.pop_back();
}
p = 1;
count = 0;
}
if(count>=3 || i > n - 1 || p > k)
{
return;
}
v.push_back(a[i]);
f(i + 1, count + 1, p * a[i], k, v, a, n);
v.pop_back();
f(i + 1, count, p, k, v, a, n);
}
int main()
{
int n;
cin >> n;
int *a=new int[n];
for(int i = 0; i < n; ++i)
{
cin >> a[i];
}
int k;
cin >> k;
//int p = 1;
vector<int>v;
f(0, 0, 1, k, v, a, n);
delete[] a;
return 0;
}
Your “reset” of p and count on success is immediately strange: why does the function need to keep looking when its caller will already try the other possibilities? But that’s just a distraction from the real issue: the balanced push_back and pop_back around the first recursive call establish and rely on an invariant where every call leaves v the same length as when it started. But the success path clears the vector and leaves it shorter, so eventually you pop_back when it’s empty and—
The joys of undefined behavior (which happened to give an infinite loop here) aside, the fix is trivial: just return after printing without modifying v at all. (Then you may find some further simplifications.)
Consider an array A with length n. Let k be the length of subsequences to be generated. What I want to do is to get the number of subsequences with length k and sum s.
Example:
A = [1,1,2,2,3]
s = 4
k = 2
So output would be 3 -> [{1,3}, {1,3}, {2,2}].
Note: 1 is considered twice as treated individually.
The total number of subsequences with length k is ⁿCₖ (Here, 10).
What I tried: I tried to generate all subsequences of length k using Pascals Identity, individually calculate their sum and check whether it is equal to sum s or not. How can I make the algorithm more efficient?
Can anyone help me with this?
I don't know much about C++ but this seems to work:
#include <iostream>
using namespace std;
#include <map>
double f(int A[], int n, int s, int k, int i, map<array<int, 3>, double> memo){
if (k == 0)
return s == 0 ? 1 : 0;
if (i == n || s < 0 || k < 0)
return 0;
return memo[array<int, 3>{s, k, i}] =
f(A, n, s - A[i], k - 1, i + 1, memo) + f(A, n, s, k, i + 1, memo);
}
int main(){
map<array<int, 3>, double> memo;
int A[5] = {1, 1, 2, 2, 3};
double result = f(A, 5, 4, 2, 0, memo);
cout << result;
}
This can be solved using the knapsack method. For each element you can either include it or exclude it. Here's the cpp code :
ll knap(int values[],int n, int i, int length, int sum) { //ll is long long
if(s<0 || i>n-1 ||l<0) return 0;
if(s==0 && l==0) return 1;
ll a = knap(values,n,i+1,l-1,s-values[i]); //including current element
ll b = knap(values,n,i+1,l,s); //not including the current element and moving on
return (a+b);
}
Briefly about the condition of the problem:
Given the numbers from 1 to n, and m stages of purification, after that follows in m lines with two numbers left and right (borders, inclusive), the range of deleting numbers (1..n), you must output all living elements after removal.
I will give an example:
n = 10, m = 3
Suppose we make an array a[1,2,3,4,5,6,7,8,9,10];
left = 1, right = 2;
After 1 deletion: a[3,4,5,6,7,8,9,10];
left = 4, right = 5;
After 2 deletion: a[3,4,5,8,9,10];
left = 3, right = 5;
After 3 deletion: a[3,4,10];
Conclusion: 3 4 10
So not everything is so simple, the restrictions are strict, namely:
n, m <= 3 * 10 ^ 5
left <= right
My attempt was as follows: I created a vector from numbers from 1 to n and deleted all elements in range [left, right], but Time Limit is coming because of the complexity.
#include <iostream>
#include <vector>
using namespace std;
#define ll uint64_t
int main() {
ll i, n, k, l, r;
cin >> n >> k;
vector <ll> a;
for (i = 1; i <= n; i++) {
a.push_back(i);
}
for (i = 1; i <= k; i++) {
cin >> l >> r;
a.erase(a.begin()+l-1,a.begin()+r);
}
cout << a.size() << endl;
for (auto i : a) {
cout << i << ' ';
}
}
How to solving this problem?
The problem is solvable using a segment tree with lazy propagation and order statistics in O((N + Q) * log(N)) which should pass in a second or two on most online judges given your constraints.
Brief Explanation
'Still Exists' Boolean Array
Let's imagine that we have a boolean array of size N that indicates for each item whether it still exists or removed. The array will be initialized with ones since no elements are removed yet.
Segment Tree
Info Query: Let's build a range-sum segment tree on top of this boolean array (True is mapped to 1 and false is mapped to 0). If we query for any [L, R] range, the segment tree answers with the number of still existing elements. (Note that L and R are indices in the original array -that includes removed and non-removed elements-)
Update Query: The only update query done on the segment tree is to set a range with zeros (marking a range of elements as removed). Since we update a range of elements to zeros, we need to use lazy propagation (No need for it if the problem required removing a single item).
The Final Output
After updating all ranges given to zeros, we can iterate over each index and check if it's zero or one, and print it if it's one, however the solution is not that easy since the ranges provided in the input are not ranges in the original array, it's actually indices in the updated array.
Updated Ranges Problem
To understand the problem more let's go through an example:
Let's assume we're working with an array of length 6, the array is initially: 1 2 3 4 5 6 and the boolean array is initially: 1 1 1 1 1 1
Let's assume that the first deletion is [2, 4], now the new array is: 1 5 6 and the new updated boolean array is: 1 0 0 0 1 1
At this point, if we were asked to print the array, we will simply go through the original array and print the values that only corresponds to true in the boolean array.
Now let's try to delete another range [1, 2], if we simply set the first two elements to zeros, then we will end up with: 0 0 0 0 1 1. Which means that we still have 5, 6 on in our array, while we actually have only 6 after the last deletion.
Order-Statistics to solve the updated ranges problem
To solve the problem, we need to add the order-statistics property to our segment tree. this property will answer the following question: Given X, find the index were the prefix sum of ones that ends with it is X, this will help us map the current [L, R] into new [L, R] that can be used with the original indexing.
To understand the mapping better, let's go back to the second step of our example:
The boolean array was: 1 0 0 0 1 1, Delete elements between L=1 and R=2, using the order-statistics property, L will be mapped to 1 and R will be mapped to 5, now we will update the range between the newL and the newR to zeros and the boolean array becomes 0 0 0 0 0 1.
Code
#include <bits/stdc++.h>
using namespace std;
class SegmentTree {
vector<int> seg, lazy;
int sz;
void build(int ind, int ns, int ne, const vector<int> &v) {
if (ns == ne) {
seg[ind] = v[ns];
return;
}
int mid = ns + (ne - ns) / 2;
build(ind * 2, ns, mid, v);
build(ind * 2 + 1, mid + 1, ne, v);
seg[ind] = seg[ind * 2] + seg[ind * 2 + 1];
}
void probagateLazy(int ind) {
if (lazy[ind]) {
lazy[ind] = 0, seg[ind] = 0;
if (ind * 2 + 1 < 4 * sz)
lazy[ind * 2] = lazy[ind * 2 + 1] = 1;
}
}
int query(int s, int e, int ind, int ns, int ne) {
probagateLazy(ind);
if (e < ns || s > ne)
return 0;
if (s <= ns && ne <= e)
return seg[ind];
int mid = ns + (ne - ns) / 2;
return query(s, e, ind * 2, ns, mid) + query(s, e, ind * 2 + 1, mid + 1, ne);
}
void update(int s, int e, int ind, int ns, int ne) {
probagateLazy(ind);
if (e < ns || s > ne)
return;
if (s <= ns && ne <= e) {
lazy[ind] = 1;
probagateLazy(ind);
return;
}
int mid = ns + (ne - ns) / 2;
update(s, e, ind * 2, ns, mid);
update(s, e, ind * 2 + 1, mid + 1, ne);
seg[ind] = seg[ind * 2] + seg[ind * 2 + 1];
}
int find(int pos, int ind, int ns, int ne) {
probagateLazy(ind);
if (ns == ne)
return ns;
probagateLazy(ind * 2);
probagateLazy(ind * 2 + 1);
int mid = ns + (ne - ns) / 2;
if (pos <= seg[ind * 2])
return find(pos, ind * 2, ns, mid);
return find(pos - seg[ind * 2], ind * 2 + 1, mid + 1, ne);
}
public:
SegmentTree(int sz, const vector<int> &v) {
this->sz = sz;
seg = vector<int>(sz * 4);
lazy = vector<int>(sz * 4);
build(1, 0, sz - 1, v);
}
int query(int s, int e) {
return query(s, e, 1, 0, sz - 1);
}
int update(int s, int e) {
update(s, e, 1, 0, sz - 1);
}
int find(int pos) {
return find(pos, 1, 0, sz - 1);
}
};
int main() {
int i, n, k, l, r;
scanf("%d %d", &n, &k);
vector<int> a;
for (i = 1; i <= n; i++) {
a.push_back(i);
}
vector<int> v(n, 1);
SegmentTree st(n, v);
while (k--) {
scanf("%d %d", &l, &r);
int newL = st.find(l);
int newR = st.find(r);
st.update(newL, newR);
}
vector<int> ans;
for (int i = 0; i < n; i++) {
if (st.query(i, i))
ans.push_back(a[i]);
}
printf("%d\n", ans.size());
for (int i = 0; i < ans.size(); i++) {
printf("%d ", ans[i]);
}
}
Black Boxing the Segment Tree
If you're not familiar with segment trees, then it's expected to find the code hard to understand, so I'll try to make it easier by ignoring the internal implementation of the segment tree and give you a quick look at its functionalities.
Query Method
The query method takes as an input the start and end index of the range to be queried and returns the summation of the elements inside this range.
Update Method
The update method takes as input the start and end index of the range to be updated, and set all items inside this range to zeros
Find Method
The find method takes as an input X and returns the first element Y were the sum of elements in the range [0, Y] is X
Other Solutions
The problem can also be solved using Splay Tree or Treap data structure.
I have a c++ program which calculates maximum of a array provided no two consecutive elements of array can be taken.
For eg:
7 3 4 6 will result in a answer of 13 .Here we chose 7 and 6 for optimal maximum.
Here is my recursive program for it.
#include <iostream>
using namespace std;
int n;
int findMax(int x,int ar[])
{
if(x < n)
return max( ar[x]+findMax(x+2,ar), findMax(x+1,ar));
return 0;
}
int main(){
int ar[]={1,7,4,4,9,5,12};
n = sizeof(ar)/sizeof(ar[0]);
cout<<findMax(0,ar);
return 0;
}
However I am more interested in the indices of array which were chosen for this purpose by my program .How can I do that efficiently.
In the above program answer should be 1,4,6 as we chose 1st , 4th and 6th element of the array for the maximum.
Note: I am using 0 based indexing.
Thanks.
A recurrence relation R(k) for the maximum sum of the first k elements of the array (with no adjacent terms) is:
R(0) = 0, R(1) = max(0, a[0])
R(k) = max(a[k] + R(k-2), R(k-1))
This is almost the same recurrence you're using in your code, but in your code your function returns the maximum sum of elements k and later.
Anyway, you can build a table of these values in linear time using dynamic programming. In pseudocode:
R = new array of length n+1
R[0] = 0
R[1] = max(0, a[0])
for i = 2 .. n
R[i] = max(a[i-1] + R[i-2], R[i-1])
If you just want the maximum sum, you can return R[n]. But you can also reconstruct the indices easily. In pseudo-code:
indices(a, R):
result = new empty vector
i = n
while i > 0
if (i == 1 and a[0] > 0) or R[i] == a[i-1] + R[i-2]
result.push_back(i-1)
i -= 2
else
i -= 1
You'll have to reverse result to get the indices in increasing order.
This is definitely not the most effective solution but probably the one with least implementation effort:
#include <iostream>
#include <vector>
using namespace std;
int n;
pair<int, vector<int> > findMax(int x, int ar[])
{
if (x < n) {
pair<int, vector<int> > max1 = findMax(x + 2, ar);
const pair<int, vector<int> > max2 = findMax(x + 1, ar);
max1.first += ar[x];
max1.second.insert(max1.second.begin(), x);
return max1.first >= max2.first ? max1 : max2;
}
return make_pair(0, vector<int>());
}
ostream& operator<<(ostream &out, const vector<int> &vec)
{
const char *sep = "";
for (int value : vec) {
out << sep << value; sep = ", ";
}
return out;
}
int main()
{
int ar[]={1,7,4,4,9,5,12};
n = sizeof ar / sizeof *ar;
const pair<int, vector<int> > maxAr = findMax(0, ar);
cout << maxAr.first << '\n'
<< maxAr.second << '\n';
return 0;
}
Output:
28
1, 4, 6
Life demo on coliru
Thereby, the return value is extended with a std::vector<int> which holds the used indices beside of the current sum.
std::max() could be used if I would provide a suitable (overloadeded) operator<() for std::pair<int, std::vector<int> >. To not make things over-complicated, I just replaced std::max() by the resp. condition.
I think below code will satisfy your need.
#include<bits/stdc++.h>
using namespace std;
int n;
void findMax(int arr[], int in, pair< int, vector<int> > tempStore,
pair< int, vector<int> > &resStore) {
if(in >=n) {
if(resStore.first < tempStore.first) {
resStore.first = tempStore.first;
resStore.second = tempStore.second;
}
return;
}
findMax(arr, in+1, tempStore, resStore);
tempStore.first += arr[in];
tempStore.second.push_back(in);
findMax(arr, in+2, tempStore, resStore);
}
int main() {
int ar[]={1,7,4,4,9,5,12};
n = sizeof(ar)/sizeof(ar[0]);
pair< int, vector<int> > resStore, tempStore;
findMax(ar, 0,tempStore,resStore);
cout<<"Result Value: "<<resStore.first;
cout<<"\nResult Index:\n";
for(int i=0; i<resStore.second.size(); i++) {
cout<<resStore.second[i]<<" ";
}
return 0;
}
How do you find the minimal product from an array? This is the problem I have and the attempted solution isn't working. What have I done wrong?
https://www.codechef.com/problems/CHRL4
After visiting a childhood friend, Chef wants to get back to his home. Friend lives at the first street, and Chef himself lives at the N-th (and the last) street. Their city is a bit special: you can move from the X-th street to the Y-th street if and only if 1 <= Y - X <= K, where K is the integer value that is given to you. Chef wants to get to home in such a way that the product of all the visited streets' special numbers is minimal (including the first and the N-th street). Please, help him to find such a product.
Input
The first line of input consists of two integer numbers - N and K - the number of streets and the value of K respectively. The second line consist of N numbers - A1, A2, ..., AN respectively, where Ai equals to the special number of the i-th street.
Output
Please output the value of the minimal possible product, modulo 1000000007.
Constraints
1 ≤ N ≤ 10^5
1 ≤ Ai ≤ 10^5
1 ≤ K ≤ N
Example
Input:
4 2
1 2 3 4.
Output:
8
#include <iostream>
using namespace std;
int P(int A[], int N, int K) {
if (N == 1) return A[0];
int m = A[0], prod = m;
for (int i = 1; i < N; ++i) {
if (1 <= A[i]-m && A[i]-m <= K) {
prod *= A[i];
}
}
return prod;
}
int main() {
int A[] = {1, 2, 3, 4};
cout << P(A, 4, 2);
}
I get 6 instead of 8.
Such problems can typically be solved by Dynamic Programming:
Construct an appropriate state variable: Let the state be S = current street. Let the factor at street S be calledC_S
For each state S, collect the possible actions: a(S) = {go to any street T for which : 1 <= C_T - C_S <= K, T <=N }, a(N) = {}.
Introduce a value function V(S) = minimal product to get from S to N. Set V(N) = C_N.
Having all this together, one can now solve the Bellman equation backwards from N, where particularly the value V(0) is sought:
V(S) = min_{allowed T} { V(T)*C_S }
Example implementation:
int main()
{
int N = 4;
int K = 2;
std::vector<int> C{1,2,3,4};
std::vector<int> V(N);
V.back() = C.back();
for(int i = N - 2; i>= 0; --i)
{
int min = std::numeric_limits<int>::max(); //possible overflow here,
//better change that
for(int j=i+1; j< N; ++j)
{
double DeltaC = C[j] - C[i];
if(DeltaC <= K && DeltaC >= 1)
{
double vt = V[j] * C[i];
if(vt < min)
{
min = vt;
}
}
}
V[i] = min;
}
std::cout<<V[0]<<std::endl;
}
DEMO
The output is 8.
Please understand the code, test it and then use it with a good conscience (whatever that means).