/** By Avikalp Srivastava **/
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<math.h>
// Get the mid value of the interval [s,e]
int get_mid(int s, int e)
{
return s+(e-s)/2;
}
// Will be used for constructing the segment tree by the constructing function construct_st
int construct_st_util(int A[],int ss,int se,int st[],int si);
// A[] : Array for which segment tree is constructed
// n : size of array A[]
int* construct_st(int A[],int n)
{
int x
= (int)(ceil)(log2
(n
)); int size
= 2*(int)pow(2,x
)-1; // Allocating proper amount of memory to st(segment tree)
int* st
= (int *)malloc(size
*sizeof(int)); // Calling helper function
construct_st_util(A,0,n-1,st,0);
return st;
}
// ss : start of segment
// se : segment end
// st[] : segment tree of array A[]
// si : current index during traversal in the segment tree
// Parameters passed initially : A[] -> original array, ss -> 0, se -> n-1, st[] -> array with apt allocated mem, si -> 0
int construct_st_util(int A[],int ss,int se,int st[],int si)
{
// If interval length is zero, we pass the array value to st[si]
if(ss==se)
{
st[si]=A[ss];
return st[si];
}
// Recursive calls to the left and right children and adding them to get value for current node
int mid= get_mid(ss,se);
st[si]=(construct_st_util(A,ss,mid,st,2*si+1)+construct_st_util(A,mid+1,se,st,2*si+2));
return st[si];
}
// Helper to get_sum function
// Lazy array may have some updates to be made
// ss : segment start of current probe
// se : segment end of current probe
// qs : query start provided by user
// qe : query end provided by the user
// si : current segment tree index in probe
int get_sum_util(int st[],int lazy[],int ss,int se,int qs, int qe,int si)
{
// If there are pending updates, complete them and assign lazy values to children
if(lazy[si]!=0)
{
st[si]=lazy[si]*(se-ss+1);
// If the node is not a leaf
if(ss!=se)
{
lazy[2*si+1]=lazy[si];
lazy[2*si+2]=lazy[si];
}
// This node now has no pending updates
lazy[si]=0;
}
if(ss>=qs&&se<=qe) return st[si]; // completely within query range, return updated sum value
if(ss>se||ss>qe||se<qs) return 0; // completely out of query range, nothing to do
// Partial Overlap case
int mid = get_mid(ss,se);
return (get_sum_util(st,lazy,ss,mid,qs,qe,2*si+1)+get_sum_util(st,lazy,mid+1,se,qs,qe,2*si+2));
}
// Get_sum of array elements from qs to qe
int get_sum(int st[],int lazy[],int n,int qs,int qe)
{
return get_sum_util(st,lazy,0,n-1,qs,qe,0);
}
// Helper to update_val function
// ss : segment start of current probe
// se : segment end of current probe
// qs : query start provided by user
// qe : query end provided by the user
// si : current segment tree index in probe
// Updates array elements from qs to qe to new_val by postponing updates and assigning them to lazy values
void update_val_util(int st[],int lazy[],int ss,int se,int qs,int qe,int new_val,int si)
{
// If there are pending updates to the current node, complete them.
if(lazy[si]!=0)
{
st[si]=lazy[si]*(se-ss+1);
// If node is not a leaf
if(se!=ss)
{
lazy[si*2+1]=lazy[si];
lazy[2*si+2]=lazy[si];
}
// No pending updates to the current node
lazy[si]=0;
}
if(ss>se||qs>se||qe<ss) return; // current node is out of query range, nothing to do.
if(ss>=qs&&qe>=se) // current node is completely in query range, update it and assign lazy values to children
{
st[si]=(new_val)*(se-ss+1);
// If current node is not a leaf
if(ss!=se)
{
lazy[2*si+1]=new_val;
lazy[2*si+2]=new_val;
}
return; // Since current node was completely in range and lazy values have been assigned to children, no need to recurse further
}
// In case the current node's range partially overlaps with the query range
int mid = get_mid(ss,se);
update_val_util(st,lazy,ss,mid,qs,qe,new_val,2*si+1); // Update left child
update_val_util(st,lazy,mid+1,se,qs,qe,new_val,2*si+2); // Update right child
st[si]=st[2*si+1]+st[2*si+2]; // Current node is sum of children
}
// Called for updating array elements from qs to qe to new_val.
void update_val(int A[],int lazy[],int n,int qs,int qe,int new_val,int st[])
{
update_val_util(st,lazy,0,n-1,qs,qe,new_val,0);
}
// Used for constructing lazy array with apt memory and initialisation.
int* construct_lazy(int n)
{
int *lazy,i;
int x
= (int)((ceil)(log2
(n
))); int size
= 2*(int)pow(2,x
)-1; lazy
=(int *)malloc(size
*sizeof(int)); for(i=0;i<size;i++) lazy[i]=0;
return lazy;
}
int main(void)
{
int A[]={1,2,6,7,3,4};
int *st,*lazy,n=6;
st= construct_st(A,n);
lazy=construct_lazy(n);
int i;
int x
= (int)((ceil)(log2
(n
))); int size
= 2*(int)pow(2,x
)-1;
printf("Initially Constructed Segment Tree : "); for(i=0;i<size;i++)
{
}
int s,e;
s=1;
e=3;
printf("\nSum is %d\n",get_sum
(st
,lazy
,n
,s
,e
)); update_val(A,lazy,n,2,4,10,st);
printf("Updated sum is %d\n",get_sum
(st
,lazy
,n
,s
,e
)); update_val(A,lazy,n,1,2,24,st);
printf("Second Updated sum is %d\n",get_sum
(st
,lazy
,n
,s
,e
)); return 0;
}
LyoqIEJ5IEF2aWthbHAgU3JpdmFzdGF2YSAqKi8KCiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlPHN0cmluZy5oPgojaW5jbHVkZTxtYXRoLmg+CgovLyBHZXQgdGhlIG1pZCB2YWx1ZSBvZiB0aGUgaW50ZXJ2YWwgW3MsZV0KaW50IGdldF9taWQoaW50IHMsIGludCBlKQp7CglyZXR1cm4gcysoZS1zKS8yOwp9CgovLyBXaWxsIGJlIHVzZWQgZm9yIGNvbnN0cnVjdGluZyB0aGUgc2VnbWVudCB0cmVlIGJ5IHRoZSBjb25zdHJ1Y3RpbmcgZnVuY3Rpb24gY29uc3RydWN0X3N0CmludCBjb25zdHJ1Y3Rfc3RfdXRpbChpbnQgQVtdLGludCBzcyxpbnQgc2UsaW50IHN0W10saW50IHNpKTsKCi8vIEFbXSA6IEFycmF5IGZvciB3aGljaCBzZWdtZW50IHRyZWUgaXMgY29uc3RydWN0ZWQKLy8gbiA6IHNpemUgb2YgYXJyYXkgQVtdCmludCogY29uc3RydWN0X3N0KGludCBBW10saW50IG4pCnsKCWludCB4PSAoaW50KShjZWlsKShsb2cyKG4pKTsKCWludCBzaXplPSAyKihpbnQpcG93KDIseCktMTsKCS8vIEFsbG9jYXRpbmcgcHJvcGVyIGFtb3VudCBvZiBtZW1vcnkgdG8gc3Qoc2VnbWVudCB0cmVlKQoJaW50KiBzdCA9IChpbnQgKiltYWxsb2Moc2l6ZSpzaXplb2YoaW50KSk7CgkvLyBDYWxsaW5nIGhlbHBlciBmdW5jdGlvbgoJY29uc3RydWN0X3N0X3V0aWwoQSwwLG4tMSxzdCwwKTsKCXJldHVybiBzdDsKfQoKLy8gc3MgOiBzdGFydCBvZiBzZWdtZW50Ci8vIHNlIDogc2VnbWVudCBlbmQKLy8gc3RbXSA6IHNlZ21lbnQgdHJlZSBvZiBhcnJheSBBW10KLy8gc2kgOiBjdXJyZW50IGluZGV4IGR1cmluZyB0cmF2ZXJzYWwgaW4gdGhlIHNlZ21lbnQgdHJlZQovLyBQYXJhbWV0ZXJzIHBhc3NlZCBpbml0aWFsbHkgOiBBW10gLT4gb3JpZ2luYWwgYXJyYXksIHNzIC0+IDAsIHNlIC0+IG4tMSwgc3RbXSAtPiBhcnJheSB3aXRoIGFwdCBhbGxvY2F0ZWQgbWVtLCBzaSAtPiAwCmludCBjb25zdHJ1Y3Rfc3RfdXRpbChpbnQgQVtdLGludCBzcyxpbnQgc2UsaW50IHN0W10saW50IHNpKQp7CiAgICAvLyBJZiBpbnRlcnZhbCBsZW5ndGggaXMgemVybywgd2UgcGFzcyB0aGUgYXJyYXkgdmFsdWUgdG8gc3Rbc2ldCglpZihzcz09c2UpCgl7CgkJc3Rbc2ldPUFbc3NdOwoJCXJldHVybiBzdFtzaV07Cgl9CgoJLy8gUmVjdXJzaXZlIGNhbGxzIHRvIHRoZSBsZWZ0IGFuZCByaWdodCBjaGlsZHJlbiBhbmQgYWRkaW5nIHRoZW0gdG8gZ2V0IHZhbHVlIGZvciBjdXJyZW50IG5vZGUKCWludCBtaWQ9IGdldF9taWQoc3Msc2UpOwoJc3Rbc2ldPShjb25zdHJ1Y3Rfc3RfdXRpbChBLHNzLG1pZCxzdCwyKnNpKzEpK2NvbnN0cnVjdF9zdF91dGlsKEEsbWlkKzEsc2Usc3QsMipzaSsyKSk7CglyZXR1cm4gc3Rbc2ldOwp9CgovLyBIZWxwZXIgdG8gZ2V0X3N1bSBmdW5jdGlvbgovLyBMYXp5IGFycmF5IG1heSBoYXZlIHNvbWUgdXBkYXRlcyB0byBiZSBtYWRlCi8vIHNzIDogc2VnbWVudCBzdGFydCBvZiBjdXJyZW50IHByb2JlCi8vIHNlIDogc2VnbWVudCBlbmQgb2YgY3VycmVudCBwcm9iZQovLyBxcyA6IHF1ZXJ5IHN0YXJ0IHByb3ZpZGVkIGJ5IHVzZXIKLy8gcWUgOiBxdWVyeSBlbmQgcHJvdmlkZWQgYnkgdGhlIHVzZXIKLy8gc2kgOiBjdXJyZW50IHNlZ21lbnQgdHJlZSBpbmRleCBpbiBwcm9iZQppbnQgZ2V0X3N1bV91dGlsKGludCBzdFtdLGludCBsYXp5W10saW50IHNzLGludCBzZSxpbnQgcXMsIGludCBxZSxpbnQgc2kpCnsKCS8vIElmIHRoZXJlIGFyZSBwZW5kaW5nIHVwZGF0ZXMsIGNvbXBsZXRlIHRoZW0gYW5kIGFzc2lnbiBsYXp5IHZhbHVlcyB0byBjaGlsZHJlbgoJaWYobGF6eVtzaV0hPTApCgl7CgkJc3Rbc2ldPWxhenlbc2ldKihzZS1zcysxKTsKCQkvLyBJZiB0aGUgbm9kZSBpcyBub3QgYSBsZWFmCgkJaWYoc3MhPXNlKQoJCXsKCQkJbGF6eVsyKnNpKzFdPWxhenlbc2ldOwoJCQlsYXp5WzIqc2krMl09bGF6eVtzaV07CgkJfQoJCS8vIFRoaXMgbm9kZSBub3cgaGFzIG5vIHBlbmRpbmcgdXBkYXRlcwoJCWxhenlbc2ldPTA7Cgl9CgoJaWYoc3M+PXFzJiZzZTw9cWUpIHJldHVybiBzdFtzaV07ICAgICAgICAgICAgICAgICAgIC8vIGNvbXBsZXRlbHkgd2l0aGluIHF1ZXJ5IHJhbmdlLCByZXR1cm4gdXBkYXRlZCBzdW0gdmFsdWUKCWlmKHNzPnNlfHxzcz5xZXx8c2U8cXMpIHJldHVybiAwOyAgICAgICAgICAgICAgICAgICAvLyBjb21wbGV0ZWx5IG91dCBvZiBxdWVyeSByYW5nZSwgbm90aGluZyB0byBkbwoKCS8vIFBhcnRpYWwgT3ZlcmxhcCBjYXNlCglpbnQgbWlkID0gZ2V0X21pZChzcyxzZSk7CglyZXR1cm4gKGdldF9zdW1fdXRpbChzdCxsYXp5LHNzLG1pZCxxcyxxZSwyKnNpKzEpK2dldF9zdW1fdXRpbChzdCxsYXp5LG1pZCsxLHNlLHFzLHFlLDIqc2krMikpOwp9CgovLyBHZXRfc3VtIG9mIGFycmF5IGVsZW1lbnRzIGZyb20gcXMgdG8gcWUKaW50IGdldF9zdW0oaW50IHN0W10saW50IGxhenlbXSxpbnQgbixpbnQgcXMsaW50IHFlKQp7CglyZXR1cm4gZ2V0X3N1bV91dGlsKHN0LGxhenksMCxuLTEscXMscWUsMCk7Cn0KCi8vIEhlbHBlciB0byB1cGRhdGVfdmFsIGZ1bmN0aW9uCi8vIHNzIDogc2VnbWVudCBzdGFydCBvZiBjdXJyZW50IHByb2JlCi8vIHNlIDogc2VnbWVudCBlbmQgb2YgY3VycmVudCBwcm9iZQovLyBxcyA6IHF1ZXJ5IHN0YXJ0IHByb3ZpZGVkIGJ5IHVzZXIKLy8gcWUgOiBxdWVyeSBlbmQgcHJvdmlkZWQgYnkgdGhlIHVzZXIKLy8gc2kgOiBjdXJyZW50IHNlZ21lbnQgdHJlZSBpbmRleCBpbiBwcm9iZQovLyBVcGRhdGVzIGFycmF5IGVsZW1lbnRzIGZyb20gcXMgdG8gcWUgdG8gbmV3X3ZhbCBieSBwb3N0cG9uaW5nIHVwZGF0ZXMgYW5kIGFzc2lnbmluZyB0aGVtIHRvIGxhenkgdmFsdWVzCnZvaWQgdXBkYXRlX3ZhbF91dGlsKGludCBzdFtdLGludCBsYXp5W10saW50IHNzLGludCBzZSxpbnQgcXMsaW50IHFlLGludCBuZXdfdmFsLGludCBzaSkKewoJLy8gSWYgdGhlcmUgYXJlIHBlbmRpbmcgdXBkYXRlcyB0byB0aGUgY3VycmVudCBub2RlLCBjb21wbGV0ZSB0aGVtLgoJaWYobGF6eVtzaV0hPTApCgl7CgkJc3Rbc2ldPWxhenlbc2ldKihzZS1zcysxKTsKCQkvLyBJZiBub2RlIGlzIG5vdCBhIGxlYWYKCQlpZihzZSE9c3MpCgkJewoJCQlsYXp5W3NpKjIrMV09bGF6eVtzaV07CgkJCWxhenlbMipzaSsyXT1sYXp5W3NpXTsKCQl9CgkJLy8gTm8gcGVuZGluZyB1cGRhdGVzIHRvIHRoZSBjdXJyZW50IG5vZGUKCQlsYXp5W3NpXT0wOwoJfQoKCWlmKHNzPnNlfHxxcz5zZXx8cWU8c3MpIHJldHVybjsgCS8vIGN1cnJlbnQgbm9kZSBpcyBvdXQgb2YgcXVlcnkgcmFuZ2UsIG5vdGhpbmcgdG8gZG8uCgoJaWYoc3M+PXFzJiZxZT49c2UpCQkJCQkvLyBjdXJyZW50IG5vZGUgaXMgY29tcGxldGVseSBpbiBxdWVyeSByYW5nZSwgdXBkYXRlIGl0IGFuZCBhc3NpZ24gbGF6eSB2YWx1ZXMgdG8gY2hpbGRyZW4KCXsKCQlzdFtzaV09KG5ld192YWwpKihzZS1zcysxKTsKCQkvLyBJZiBjdXJyZW50IG5vZGUgaXMgbm90IGEgbGVhZgoJCWlmKHNzIT1zZSkKCQl7CgkJCWxhenlbMipzaSsxXT1uZXdfdmFsOwoJCQlsYXp5WzIqc2krMl09bmV3X3ZhbDsKCQl9CgkJcmV0dXJuOwkJCQkJCSAgLy8gU2luY2UgY3VycmVudCBub2RlIHdhcyBjb21wbGV0ZWx5IGluIHJhbmdlIGFuZCBsYXp5IHZhbHVlcyBoYXZlIGJlZW4gYXNzaWduZWQgdG8gY2hpbGRyZW4sIG5vIG5lZWQgdG8gcmVjdXJzZSBmdXJ0aGVyCgl9CgoJLy8gSW4gY2FzZSB0aGUgY3VycmVudCBub2RlJ3MgcmFuZ2UgcGFydGlhbGx5IG92ZXJsYXBzIHdpdGggdGhlIHF1ZXJ5IHJhbmdlCglpbnQgbWlkID0gZ2V0X21pZChzcyxzZSk7Cgl1cGRhdGVfdmFsX3V0aWwoc3QsbGF6eSxzcyxtaWQscXMscWUsbmV3X3ZhbCwyKnNpKzEpOwkJLy8gVXBkYXRlIGxlZnQgY2hpbGQKCXVwZGF0ZV92YWxfdXRpbChzdCxsYXp5LG1pZCsxLHNlLHFzLHFlLG5ld192YWwsMipzaSsyKTsJCS8vIFVwZGF0ZSByaWdodCBjaGlsZAoKCXN0W3NpXT1zdFsyKnNpKzFdK3N0WzIqc2krMl07CQkJCQkJCQkvLyBDdXJyZW50IG5vZGUgaXMgc3VtIG9mIGNoaWxkcmVuCn0KCi8vIENhbGxlZCBmb3IgdXBkYXRpbmcgYXJyYXkgZWxlbWVudHMgZnJvbSBxcyB0byBxZSB0byBuZXdfdmFsLgp2b2lkIHVwZGF0ZV92YWwoaW50IEFbXSxpbnQgbGF6eVtdLGludCBuLGludCBxcyxpbnQgcWUsaW50IG5ld192YWwsaW50IHN0W10pCnsKCXVwZGF0ZV92YWxfdXRpbChzdCxsYXp5LDAsbi0xLHFzLHFlLG5ld192YWwsMCk7Cn0KCi8vIFVzZWQgZm9yIGNvbnN0cnVjdGluZyBsYXp5IGFycmF5IHdpdGggYXB0IG1lbW9yeSBhbmQgaW5pdGlhbGlzYXRpb24uCmludCogY29uc3RydWN0X2xhenkoaW50IG4pCnsKCWludCAqbGF6eSxpOwoJaW50IHg9IChpbnQpKChjZWlsKShsb2cyKG4pKSk7CglpbnQgc2l6ZT0gMiooaW50KXBvdygyLHgpLTE7CglsYXp5PShpbnQgKiltYWxsb2Moc2l6ZSpzaXplb2YoaW50KSk7Cglmb3IoaT0wO2k8c2l6ZTtpKyspIGxhenlbaV09MDsKCXJldHVybiBsYXp5Owp9CgppbnQgbWFpbih2b2lkKQp7CglpbnQgQVtdPXsxLDIsNiw3LDMsNH07CglpbnQgKnN0LCpsYXp5LG49NjsKCXN0PSBjb25zdHJ1Y3Rfc3QoQSxuKTsKCWxhenk9Y29uc3RydWN0X2xhenkobik7CglpbnQgaTsKCWludCB4PSAoaW50KSgoY2VpbCkobG9nMihuKSkpOwoJaW50IHNpemU9IDIqKGludClwb3coMix4KS0xOwoJCglwcmludGYoIkluaXRpYWxseSBDb25zdHJ1Y3RlZCBTZWdtZW50IFRyZWUgOiAiKTsKCWZvcihpPTA7aTxzaXplO2krKykKCXsKCQlwcmludGYoIiVkICIsc3RbaV0pOwoJfQoJCglpbnQgcyxlOwoJcz0xOwoJZT0zOwoJcHJpbnRmKCJcblN1bSBpcyAlZFxuIixnZXRfc3VtKHN0LGxhenksbixzLGUpKTsKCXVwZGF0ZV92YWwoQSxsYXp5LG4sMiw0LDEwLHN0KTsKCXByaW50ZigiVXBkYXRlZCBzdW0gaXMgJWRcbiIsZ2V0X3N1bShzdCxsYXp5LG4scyxlKSk7Cgl1cGRhdGVfdmFsKEEsbGF6eSxuLDEsMiwyNCxzdCk7CglwcmludGYoIlNlY29uZCBVcGRhdGVkIHN1bSBpcyAlZFxuIixnZXRfc3VtKHN0LGxhenksbixzLGUpKTsKCXJldHVybiAwOwp9Cgo=