I have been trying out this problem on Hackerearth.
This is my code:
#include<bits/stdc++.h>
using namespace std;
int evencount[400004];
bool A[100001];
int num;
void build(int node,int start,int end)
{
if(start==end)
{
evencount[node]=(A[start]%2==0);
return;
}
int mid=start+(end-start)/2;
build(2*node+1,start,mid);
build(2*node+2,mid+1,end);
int left=2*node+1;
int right=2*node+2;
evencount[node]=evencount[left]+evencount[right];
}
void update(int node,int start,int end,int idx,int val)
{
if(start==end)
{
A[idx]=val%2;
evencount[node]=(val%2==0);
return;
}
int mid=start+(end-start)/2;
if(idx <= mid)
{
update(2*node+1,start,mid,idx,val);
}
else{
update(2*node+2,mid+1,end,idx,val);
}
int left=2*node+1;
int right=2*node+2;
evencount[node]=evencount[left]+evencount[right];
}
int query(int node,int start,int end,int left,int right)
{
if(end < left || start > right)
{
return 0;
}
if(left<=start && end>=right)
return evencount[node];
int mid=start+(end-start)/2;
int p1,p2;
p1=query(2*node+1,start,mid,left,right);
p2=query(2*node+2,mid+1,end,left,right);
return p1+p2;
}
int main(){
int N;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>num;
A[i]=num%2;
}
int Q;
cin>>Q;
for(int i=0;i<Q;i++)
{
int q,a,b;
cin>>q>>a>>b;
if(q==0)
update(0,0,N,a-1,b);
else
{
int t=query(0,0,N,a-1,b-1);
if(q==1)
cout<<t<<endl;
else
cout<<(b-a+1)-t<<endl;
}
}
}
I have optimized it as much as I can. It is still giving memory limit exceeded. Where and how can I optimize this code further in terms of memory ?
Hey!
Random observation based on the problem URL: Have you considered to use Fenwick / BIT tree which requires 4 times less memory?
Some facts about memory limit for this problem:
Why he exceeded 256MB with 4MB Segment Tree?
You can use fenwick tree for optimizing memory.
Yes, but the question can be solved in segment tree as well, according to the question tag. But I will try Fenwick as well. Thanks.
You can decrease memory usage by this trick: Let your current node be x. Let y = (l + r) / 2. (l and r are your node intervals) Now the left child of node x will be x + 1. And the right child will be x + ((y — l + 1) << 1). The memory usage will be 2n (or 2n — 1). If you wanna know why this works, check cp algorithms segtree section. (The ids of nodes that i explained where all 0_based.)
I added in your code 3 types of assert:
assert_re(bool q)
,assert_tle(bool q)
andassert_mle(bool q)
. Ifbool q
will be false, solution will be finished with verdicts RE, TLE or MLE and you will see which assert was failed. https://pastebin.com/iAXFHf05assert_mle(depth <= 20);
was failed at line 72, it means, that you have a bug andquery
function never ends and have infinity recursion calls without return. So, you have a bug in your logic, you should debug it and fix it.There are several compilation flags, which can detect problem without code change:
. Then, if you run original code on sample, you will get following exceptions:
Obviously, there is an infinite recursion here.
Awesome. Same result can be given by running in Codeforces Custom Invocation with Clang++17 Diagnostics on sample, but without stack trace.
Clang++17 Diagnostics on following code just write 2:
Whereas mine compiler warnings me:
And then writes 2)
Kind of off-topic, but why
-fuse-ld=gold
? Does default linker (ld
in Linux) have some problem?Yes:
I google it and find this. So I just add this flag to my Makefile)
I use a superset of your compile flags in my makefile. I never had a problem.
What platform are you on?
Also, as per the last comment on your linked thread, it was a bug in G++7 and fixed in all distros a year back. It's weird that you still get that error.
Ubuntu 16.04 LTS
gcc version 5.5.0 20171010
Your flags on my computer get this eror:
If I set
-Wshift-overflow=
to 0 or 1 or 2, then I get the same error as in the previous comment.Offtop. MikeMirzayanov, why one dollar in editing comment changes to three dollars in comment? How can I write exactly one dollar?
GCC 7 (7.3.0-16ubuntu3) is still broken on Ubuntu 16.04 and earlier.
— StackoverflowThis is regarding using
UBsan
with GCC. This leads me to believe that this bug is unfixable for you till you upgrade your Ubuntu version.Conclusion: the alternative linker is necessary for you.
Read the comments and the corresponding changes I made to your code. Do reply back if you don't understand the reasoning behind the changes, although I suggest you work them out yourself to understand where you went wrong :)
I submitted the commented code and it got accepted. Also, you can look at my code for reference.