Levelwise GCD / LCM交替段树是一个段树,因此在每个级别上,操作GCD和LCM都是交替的。在1级换句话说,左,右子树由GCD操作即父节点=左子右GCD儿童和2级左结合在一起
和右子树通过LCM操作合并在一起,即父节点=左子节点LCM右子节点
这种类型的细分树具有以下类型的结构:
操作(GCD)和(LCM)指示执行了哪个操作来合并子节点
给定N个叶节点,任务是构建这样的段树并打印根节点。
例子:
Input : arr[] = { 5, 4, 8, 10, 6 }
Output : Value at Root Node = 2
Explanation : The image given above shows the
segment tree corresponding to the given
set leaf nodes.
先决条件:段树
在此分段树中,我们进行两项操作: -GCD和LCM 。
现在,与递归传递给子树的信息一起,由于这些操作逐级交替,因此也传递了与要在该级进行的操作有关的信息。重要的是要注意,父节点在调用其左子节点和右子节点时,会将相同的操作信息传递给两个子节点,因为它们在同一级别上。
让我们分别用0和1表示两个操作,即GCD和LCM。然后,如果在级别i上执行GCD操作,则将在级别(i +1)下执行LCM操作。因此,如果级别i的运算为0,则级别(i + 1)的运算为1。
Operation at Level (i + 1) = ! (Operation at Level i)
where,
Operation at Level i ∊ {0, 1}
对图像的仔细分析表明,如果树的高度均匀,则根节点是其左,右子级的LCM操作的结果,否则是GCD操作的结果。
CPP
#include
using namespace std;
// Recursive function to return gcd of a and b
int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a-b, b);
return gcd(a, b-a);
}
// A utility function to get the middle index from
// corner indexes.
int getMid(int s, int e) { return s + (e - s) / 2; }
void STconstructUtill(int arr[], int ss, int se, int* st,
int si, int op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se) {
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
STconstructUtill(arr, ss, mid, st, si * 2 + 1, !op);
STconstructUtill(arr, mid + 1, se, st, si * 2 + 2, !op);
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = __gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
int* STconstruct(int arr[], int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(ceil(log2(n)));
// maximum size of segment tree
int max_size = 2 * (int)pow(2, x) - 1;
// allocate memory
int* st = new int[max_size];
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
int main()
{
int arr[] = { 5, 4, 8, 10, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
// Build segment tree
int* st = STconstruct(arr, n);
// 0-based indexing in segment tree
int rootIndex = 0;
cout << "Value at Root Node = " << st[rootIndex];
return 0;
}
Java
import java.io.*;
import java.util.*;
class GFG
{
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// A utility function to get the middle index from
// corner indexes.
static int getMid(int s, int e) { return s + (e - s) / 2; }
static void STconstructUtill(int[] arr, int ss,
int se, int[] st,
int si, boolean op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
STconstructUtill(arr, ss, mid, st, si * 2 + 1, !op);
STconstructUtill(arr, mid + 1, se, st, si * 2 + 2, !op);
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if(op == true)
{
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else
{
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
static int[] STconstruct(int arr[], int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(Math.ceil((Math.log(n)/Math.log(2))));
// maximum size of segment tree
int max_size = 2 * (int)Math.pow(2, x) - 1;
// allocate memory
int[] st = new int[max_size];
boolean opAtRoot;
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
if(x % 2 == 0)
{
opAtRoot = false;
}
else
{
opAtRoot = true;
}
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
// Driver code
public static void main (String[] args)
{
int[] arr = { 5, 4, 8, 10, 6 };
int n = arr.length;
// Build segment tree
int[] st=STconstruct(arr, n);
// 0-based indexing in segment tree
System.out.println("Value at Root Node = " + st[0]);
}
}
// This code is contributed by avanitrachhadiya2155
Python3
from math import ceil,floor,log
# Recursive function to return gcd of a and b
def gcd(a, b):
# Everything divides 0
if (a == 0 or b == 0):
return 0
# base case
if (a == b):
return a
# a is greater
if (a > b):
return gcd(a - b, b)
return gcd(a, b - a)
# A utility function to get the middle index from
# corner indexes.
def getMid(s, e):
return s + (e - s) // 2
def STconstructUtill(arr, ss, se, st, si, op):
# If there is one element in array, store it in
# current node of segment tree and return
if (ss == se):
st[si] = arr[ss]
return
# If there are more than one elements, then recur
# for left and right subtrees and store the sum of
# values in this node
mid = getMid(ss, se)
# Build the left and the right subtrees by using
# the fact that operation at level (i + 1) = !
# (operation at level i)
STconstructUtill(arr, ss, mid, st, si * 2 + 1, not op)
STconstructUtill(arr, mid + 1, se, st, si * 2 + 2, not op)
# merge the left and right subtrees by checking
# the operation to be carried. If operation = 1,
# then do GCD else LCM
if (op == 1):
# GCD operation
st[si] =gcd(st[2 * si + 1], st[2 * si + 2])
else :
# LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) //(gcd(st[2 * si + 1], st[2 * si + 2]))
#
# /* Function to construct segment tree from given array.
# This function allocates memory for segment tree and
# calls STconstructUtil() to fill the allocated memory */
def STconstruct(arr, n):
# Allocate memory for segment tree
# Height of segment tree
x = ceil(log(n, 2))
# maximum size of segment tree
max_size = 2 *pow(2, x) - 1
# allocate memory
st = [0]*max_size
# operation = 1(GCD) if Height of tree is
# even else it is 0(LCM) for the root node
if (x % 2 == 0):
opAtRoot = 0
else:
opAtRoot = 1
# Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot)
# Return the constructed segment tree
return st
# Driver code
if __name__ == '__main__':
arr = [5, 4, 8, 10, 6]
n = len(arr)
# Build segment tree
st = STconstruct(arr, n)
# 0-based indexing in segment tree
rootIndex = 0
print("Value at Root Node = ",st[rootIndex])
# This code is contributed by mohit kumar 29
C#
using System;
class GFG
{
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// A utility function to get the middle index from
// corner indexes.
static int getMid(int s, int e) { return s + (e - s) / 2; }
static void STconstructUtill(int[] arr, int ss,
int se, int[] st,
int si, bool op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
STconstructUtill(arr, ss, mid, st, si * 2 + 1, !op);
STconstructUtill(arr, mid + 1, se, st, si * 2 + 2, !op);
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if(op == true)
{
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else
{
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
static int[] STconstruct(int[] arr, int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(Math.Ceiling((Math.Log(n)/Math.Log(2))));
// maximum size of segment tree
int max_size = 2 * (int)Math.Pow(2, x) - 1;
// allocate memory
int[] st = new int[max_size];
bool opAtRoot;
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
if(x % 2 == 0)
{
opAtRoot = false;
}
else
{
opAtRoot = true;
}
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
// Driver code
static public void Main ()
{
int[] arr = { 5, 4, 8, 10, 6 };
int n = arr.Length;
// Build segment tree
int[] st=STconstruct(arr, n);
// 0-based indexing in segment tree
Console.WriteLine("Value at Root Node = " + st[0]);
}
}
// This code is contributed by rag2127
Javascript
CPP
#include
using namespace std;
// Recursive function to return gcd of a and b
int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a-b, b);
return gcd(a, b-a);
}
// A utility function to get the middle index from
// corner indexes.
int getMid(int s, int e) { return s + (e - s) / 2; }
void STconstructUtill(int arr[], int ss, int se, int* st,
int si, int op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se) {
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
STconstructUtill(arr, ss, mid, st, si * 2 + 1, !op);
STconstructUtill(arr, mid + 1, se, st, si * 2 + 2, !op);
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
void updateUtil(int* st, int ss, int se, int ind, int val,
int si, int op)
{
// Base Case: If the input index lies outside
// this segment
if (ind < ss || ind > se)
return;
// If the input index is in range of this node,
// then update the value of the node and its
// children
// leaf node
if (ss == se && ss == ind) {
st[si] = val;
return;
}
int mid = getMid(ss, se);
// Update the left and the right subtrees by
// using the fact that operation at level
// (i + 1) = ! (operation at level i)
updateUtil(st, ss, mid, ind, val, 2 * si + 1, !op);
updateUtil(st, mid + 1, se, ind, val, 2 * si + 2, !op);
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
void update(int arr[], int* st, int n, int ind, int val)
{
// Check for erroneous input index
if (ind < 0 || ind > n - 1) {
printf("Invalid Input");
return;
}
// Height of segment tree
int x = (int)(ceil(log2(n)));
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
arr[ind] = val;
// Update the values of nodes in segment tree
updateUtil(st, 0, n - 1, ind, val, 0, opAtRoot);
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
int* STconstruct(int arr[], int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(ceil(log2(n)));
// maximum size of segment tree
int max_size = 2 * (int)pow(2, x) - 1;
// allocate memory
int* st = new int[max_size];
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
int main()
{
int arr[] = { 5, 4, 8, 10, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
// Build segment tree
int* st = STconstruct(arr, n);
// 0-based indexing in segment tree
int rootIndex = 0;
cout << "Old Value at Root Node = " <<
st[rootIndex] << endl;
// perform update arr[2] = 7
update(arr, st, n, 2, 7);
cout << "New Value at Root Node = " <<
st[rootIndex] << endl;
return 0;
}
Java
import java.util.*;
public class GFG
{
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// A utility function to get the middle index from
// corner indexes.
static int getMid(int s, int e)
{
return s + (e - s) / 2;
}
static void STconstructUtill(int[] arr, int ss, int se, int[] st,
int si, int op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
if(op != 0)
{
STconstructUtill(arr, ss, mid, st,
si * 2 + 1, 0);
}
else{
STconstructUtill(arr, ss, mid, st,
si * 2 + 1, 1);
}
if(op != 0)
{
STconstructUtill(arr, mid + 1, se, st,
si * 2 + 2, 0);
}
else{
STconstructUtill(arr, mid + 1, se, st,
si * 2 + 2, 1);
}
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1)
{
// GCD operation
st[si] = gcd(st[2 * si + 1],
st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
static void updateUtil(int[] st, int ss, int se,
int ind, int val,
int si, int op)
{
// Base Case: If the input index lies outside
// this segment
if (ind < ss || ind > se)
return;
// If the input index is in range of this node,
// then update the value of the node and its
// children
// leaf node
if (ss == se && ss == ind)
{
st[si] = val;
return;
}
int mid = getMid(ss, se);
// Update the left and the right subtrees by
// using the fact that operation at level
// (i + 1) = ! (operation at level i)
if(op != 0)
{
updateUtil(st, ss, mid, ind,
val, 2 * si + 1, 0);
}
else{
updateUtil(st, ss, mid, ind,
val, 2 * si + 1, 1);
}
if(op != 0)
{
updateUtil(st, mid + 1, se, ind,
val, 2 * si + 2, 0);
}
else{
updateUtil(st, mid + 1, se, ind,
val, 2 * si + 2, 1);
}
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
static void update(int[] arr, int[] st,
int n, int ind, int val)
{
// Check for erroneous input index
if (ind < 0 || ind > n - 1)
{
System.out.print("Invalid Input");
return;
}
// Height of segment tree
int x = (int)(Math.ceil(Math.log(n) / Math.log(2)));
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
arr[ind] = val;
// Update the values of nodes in segment tree
updateUtil(st, 0, n - 1, ind, val, 0, opAtRoot);
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
static int[] STconstruct(int[] arr, int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(Math.ceil(Math.log(n) / Math.log(2)));
// maximum size of segment tree
int max_size = 2 * (int)Math.pow(2, x) - 1;
// allocate memory
int[] st = new int[max_size];
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
// Driver code
public static void main(String[] args)
{
int[] arr = { 5, 4, 8, 10, 6 };
int n = arr.length;
// Build segment tree
int[] st = STconstruct(arr, n);
// 0-based indexing in segment tree
int rootIndex = 0;
System.out.println("Old Value at Root Node = " + st[rootIndex]);
// perform update arr[2] = 7
update(arr, st, n, 2, 7);
System.out.println("New Value at Root Node = " + st[rootIndex]);
}
}
// This code is contributed by divyeshrabadiya07.
C#
using System;
class GFG
{
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// A utility function to get the middle index from
// corner indexes.
static int getMid(int s, int e)
{
return s + (e - s) / 2;
}
static void STconstructUtill(int[] arr, int ss, int se, int[] st,
int si, int op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
if(op != 0)
{
STconstructUtill(arr, ss, mid, st,
si * 2 + 1, 0);
}
else{
STconstructUtill(arr, ss, mid, st,
si * 2 + 1, 1);
}
if(op != 0)
{
STconstructUtill(arr, mid + 1, se, st,
si * 2 + 2, 0);
}
else{
STconstructUtill(arr, mid + 1, se, st,
si * 2 + 2, 1);
}
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1)
{
// GCD operation
st[si] = gcd(st[2 * si + 1],
st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
static void updateUtil(int[] st, int ss, int se,
int ind, int val,
int si, int op)
{
// Base Case: If the input index lies outside
// this segment
if (ind < ss || ind > se)
return;
// If the input index is in range of this node,
// then update the value of the node and its
// children
// leaf node
if (ss == se && ss == ind)
{
st[si] = val;
return;
}
int mid = getMid(ss, se);
// Update the left and the right subtrees by
// using the fact that operation at level
// (i + 1) = ! (operation at level i)
if(op != 0)
{
updateUtil(st, ss, mid, ind,
val, 2 * si + 1, 0);
}
else{
updateUtil(st, ss, mid, ind,
val, 2 * si + 1, 1);
}
if(op != 0)
{
updateUtil(st, mid + 1, se, ind,
val, 2 * si + 2, 0);
}
else{
updateUtil(st, mid + 1, se, ind,
val, 2 * si + 2, 1);
}
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
static void update(int[] arr, int[] st,
int n, int ind, int val)
{
// Check for erroneous input index
if (ind < 0 || ind > n - 1)
{
Console.Write("Invalid Input");
return;
}
// Height of segment tree
int x = (int)(Math.Ceiling(Math.Log(n, 2)));
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
arr[ind] = val;
// Update the values of nodes in segment tree
updateUtil(st, 0, n - 1, ind, val, 0, opAtRoot);
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
static int[] STconstruct(int[] arr, int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(Math.Ceiling(Math.Log(n, 2)));
// maximum size of segment tree
int max_size = 2 * (int)Math.Pow(2, x) - 1;
// allocate memory
int[] st = new int[max_size];
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
// Driver code
static void Main()
{
int[] arr = { 5, 4, 8, 10, 6 };
int n = arr.Length;
// Build segment tree
int[] st = STconstruct(arr, n);
// 0-based indexing in segment tree
int rootIndex = 0;
Console.WriteLine("Old Value at Root Node = " + st[rootIndex]);
// perform update arr[2] = 7
update(arr, st, n, 2, 7);
Console.WriteLine("New Value at Root Node = " + st[rootIndex]);
}
}
// This code is contributed by divyesh072019.
Javascript
输出:
Value at Root Node = 2
树的构造时间复杂度为O(n),因为总共有2 * n-1个节点,并且每个节点的值us都被一次计算出来。
现在要执行点更新,即用给定的索引和值更新值,可以通过遍历树到叶节点并执行更新来完成。
返回到根节点时,我们通过传递要在每个级别执行的操作并存储将其操作应用于其左子项和右子项的值并将结果存储到来再次构建类似于build()函数的树。该节点。
执行更新后,请考虑以下细分树,
arr [2] = 7
现在,更新后的细分树如下所示:
在此,黑色的节点表示已对其进行更新的事实。
CPP
#include
using namespace std;
// Recursive function to return gcd of a and b
int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a-b, b);
return gcd(a, b-a);
}
// A utility function to get the middle index from
// corner indexes.
int getMid(int s, int e) { return s + (e - s) / 2; }
void STconstructUtill(int arr[], int ss, int se, int* st,
int si, int op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se) {
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
STconstructUtill(arr, ss, mid, st, si * 2 + 1, !op);
STconstructUtill(arr, mid + 1, se, st, si * 2 + 2, !op);
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
void updateUtil(int* st, int ss, int se, int ind, int val,
int si, int op)
{
// Base Case: If the input index lies outside
// this segment
if (ind < ss || ind > se)
return;
// If the input index is in range of this node,
// then update the value of the node and its
// children
// leaf node
if (ss == se && ss == ind) {
st[si] = val;
return;
}
int mid = getMid(ss, se);
// Update the left and the right subtrees by
// using the fact that operation at level
// (i + 1) = ! (operation at level i)
updateUtil(st, ss, mid, ind, val, 2 * si + 1, !op);
updateUtil(st, mid + 1, se, ind, val, 2 * si + 2, !op);
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
void update(int arr[], int* st, int n, int ind, int val)
{
// Check for erroneous input index
if (ind < 0 || ind > n - 1) {
printf("Invalid Input");
return;
}
// Height of segment tree
int x = (int)(ceil(log2(n)));
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
arr[ind] = val;
// Update the values of nodes in segment tree
updateUtil(st, 0, n - 1, ind, val, 0, opAtRoot);
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
int* STconstruct(int arr[], int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(ceil(log2(n)));
// maximum size of segment tree
int max_size = 2 * (int)pow(2, x) - 1;
// allocate memory
int* st = new int[max_size];
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
int main()
{
int arr[] = { 5, 4, 8, 10, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
// Build segment tree
int* st = STconstruct(arr, n);
// 0-based indexing in segment tree
int rootIndex = 0;
cout << "Old Value at Root Node = " <<
st[rootIndex] << endl;
// perform update arr[2] = 7
update(arr, st, n, 2, 7);
cout << "New Value at Root Node = " <<
st[rootIndex] << endl;
return 0;
}
Java
import java.util.*;
public class GFG
{
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// A utility function to get the middle index from
// corner indexes.
static int getMid(int s, int e)
{
return s + (e - s) / 2;
}
static void STconstructUtill(int[] arr, int ss, int se, int[] st,
int si, int op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
if(op != 0)
{
STconstructUtill(arr, ss, mid, st,
si * 2 + 1, 0);
}
else{
STconstructUtill(arr, ss, mid, st,
si * 2 + 1, 1);
}
if(op != 0)
{
STconstructUtill(arr, mid + 1, se, st,
si * 2 + 2, 0);
}
else{
STconstructUtill(arr, mid + 1, se, st,
si * 2 + 2, 1);
}
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1)
{
// GCD operation
st[si] = gcd(st[2 * si + 1],
st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
static void updateUtil(int[] st, int ss, int se,
int ind, int val,
int si, int op)
{
// Base Case: If the input index lies outside
// this segment
if (ind < ss || ind > se)
return;
// If the input index is in range of this node,
// then update the value of the node and its
// children
// leaf node
if (ss == se && ss == ind)
{
st[si] = val;
return;
}
int mid = getMid(ss, se);
// Update the left and the right subtrees by
// using the fact that operation at level
// (i + 1) = ! (operation at level i)
if(op != 0)
{
updateUtil(st, ss, mid, ind,
val, 2 * si + 1, 0);
}
else{
updateUtil(st, ss, mid, ind,
val, 2 * si + 1, 1);
}
if(op != 0)
{
updateUtil(st, mid + 1, se, ind,
val, 2 * si + 2, 0);
}
else{
updateUtil(st, mid + 1, se, ind,
val, 2 * si + 2, 1);
}
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
static void update(int[] arr, int[] st,
int n, int ind, int val)
{
// Check for erroneous input index
if (ind < 0 || ind > n - 1)
{
System.out.print("Invalid Input");
return;
}
// Height of segment tree
int x = (int)(Math.ceil(Math.log(n) / Math.log(2)));
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
arr[ind] = val;
// Update the values of nodes in segment tree
updateUtil(st, 0, n - 1, ind, val, 0, opAtRoot);
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
static int[] STconstruct(int[] arr, int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(Math.ceil(Math.log(n) / Math.log(2)));
// maximum size of segment tree
int max_size = 2 * (int)Math.pow(2, x) - 1;
// allocate memory
int[] st = new int[max_size];
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
// Driver code
public static void main(String[] args)
{
int[] arr = { 5, 4, 8, 10, 6 };
int n = arr.length;
// Build segment tree
int[] st = STconstruct(arr, n);
// 0-based indexing in segment tree
int rootIndex = 0;
System.out.println("Old Value at Root Node = " + st[rootIndex]);
// perform update arr[2] = 7
update(arr, st, n, 2, 7);
System.out.println("New Value at Root Node = " + st[rootIndex]);
}
}
// This code is contributed by divyeshrabadiya07.
C#
using System;
class GFG
{
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0 || b == 0)
return 0;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// A utility function to get the middle index from
// corner indexes.
static int getMid(int s, int e)
{
return s + (e - s) / 2;
}
static void STconstructUtill(int[] arr, int ss, int se, int[] st,
int si, int op)
{
// If there is one element in array, store it in
// current node of segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return;
}
// If there are more than one elements, then recur
// for left and right subtrees and store the sum of
// values in this node
int mid = getMid(ss, se);
// Build the left and the right subtrees by using
// the fact that operation at level (i + 1) = !
// (operation at level i)
if(op != 0)
{
STconstructUtill(arr, ss, mid, st,
si * 2 + 1, 0);
}
else{
STconstructUtill(arr, ss, mid, st,
si * 2 + 1, 1);
}
if(op != 0)
{
STconstructUtill(arr, mid + 1, se, st,
si * 2 + 2, 0);
}
else{
STconstructUtill(arr, mid + 1, se, st,
si * 2 + 2, 1);
}
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1)
{
// GCD operation
st[si] = gcd(st[2 * si + 1],
st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
static void updateUtil(int[] st, int ss, int se,
int ind, int val,
int si, int op)
{
// Base Case: If the input index lies outside
// this segment
if (ind < ss || ind > se)
return;
// If the input index is in range of this node,
// then update the value of the node and its
// children
// leaf node
if (ss == se && ss == ind)
{
st[si] = val;
return;
}
int mid = getMid(ss, se);
// Update the left and the right subtrees by
// using the fact that operation at level
// (i + 1) = ! (operation at level i)
if(op != 0)
{
updateUtil(st, ss, mid, ind,
val, 2 * si + 1, 0);
}
else{
updateUtil(st, ss, mid, ind,
val, 2 * si + 1, 1);
}
if(op != 0)
{
updateUtil(st, mid + 1, se, ind,
val, 2 * si + 2, 0);
}
else{
updateUtil(st, mid + 1, se, ind,
val, 2 * si + 2, 1);
}
// merge the left and right subtrees by checking
// the operation to be carried. If operation = 1,
// then do GCD else LCM
if (op == 1) {
// GCD operation
st[si] = gcd(st[2 * si + 1], st[2 * si + 2]);
}
else {
// LCM operation
st[si] = (st[2 * si + 1] * st[2 * si + 2]) /
(gcd(st[2 * si + 1], st[2 * si + 2]));
}
}
static void update(int[] arr, int[] st,
int n, int ind, int val)
{
// Check for erroneous input index
if (ind < 0 || ind > n - 1)
{
Console.Write("Invalid Input");
return;
}
// Height of segment tree
int x = (int)(Math.Ceiling(Math.Log(n, 2)));
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
arr[ind] = val;
// Update the values of nodes in segment tree
updateUtil(st, 0, n - 1, ind, val, 0, opAtRoot);
}
/* Function to construct segment tree from given array.
This function allocates memory for segment tree and
calls STconstructUtil() to fill the allocated memory */
static int[] STconstruct(int[] arr, int n)
{
// Allocate memory for segment tree
// Height of segment tree
int x = (int)(Math.Ceiling(Math.Log(n, 2)));
// maximum size of segment tree
int max_size = 2 * (int)Math.Pow(2, x) - 1;
// allocate memory
int[] st = new int[max_size];
// operation = 1(GCD) if Height of tree is
// even else it is 0(LCM) for the root node
int opAtRoot = (x % 2 == 0 ? 0 : 1);
// Fill the allocated memory st
STconstructUtill(arr, 0, n - 1, st, 0, opAtRoot);
// Return the constructed segment tree
return st;
}
// Driver code
static void Main()
{
int[] arr = { 5, 4, 8, 10, 6 };
int n = arr.Length;
// Build segment tree
int[] st = STconstruct(arr, n);
// 0-based indexing in segment tree
int rootIndex = 0;
Console.WriteLine("Old Value at Root Node = " + st[rootIndex]);
// perform update arr[2] = 7
update(arr, st, n, 2, 7);
Console.WriteLine("New Value at Root Node = " + st[rootIndex]);
}
}
// This code is contributed by divyesh072019.
Java脚本
输出:
Old Value at Root Node = 2
New Value at Root Node = 1
更新的时间复杂度也是O(Logn)。为了更新叶值,在每个级别处理一个节点,并且级别数为O(Logn)。