Given a string S of length N and a 2D array of strings Q[][] consisting of M queries of the following type:
- Query(“U”, “I”, “X”): Update the character at index I with the character X.
- Query(“S”, “L”, “R”): Print the sum of the squares of the position of the characters in the substring {S[L], …., S[R]} according to the English alphabets.
Examples:
Input: S = “horje”, Q[][] = {{“S”, “0”, “2”}, {“S”, “1”, “2”}, {“U”, “1”, “a”}, {“S”, “0”, “2”}, {“S”, “4”, “5”}} Output: 99 50 75 397 Explanation: For Query(“S”, “0”, “2”), sum of squares of the positions of the characters in the substring “gee” = 7*7 + 5*5 + 5*5 = 99. For Query(“S”, “1”, “2”), sum of squares of the positions of the character in the substring “ee” = 5*5 + 5*5 = 50. For Query(“U”, “1”, “a”): Replacing S[1] by ‘a’ modifies S to “gaeksforgeeks”. For Query(“S”, “0”, “2”), sum of squares of the positions of the characters in the substring “gae” = 7*7 + 1*1 + 5*5 = 75. For Query(“S”, “4”, “5”), sum of squares of the positions of the characters in the substring “ks” = 19*19 + 36 = 397
Input: S = “horje”, Q[][] = {{“S”, “1”, “2”}} Output: 50
Naive Approach: The simplest approach to solve the problem is to traverse the array Q[][] for each query and for queries of type ‘S’, simply traverse the substring {S[L], …, S[R]} and print the sum of squares of the positions of the characters in English alphabets. In each iteration to perform the query of type ‘U’, simply assign X to S[I].
Time Complexity: O(N * M) Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized by using Segment Tree data structure. Follow the steps below to solve the problem:
- Initialize a segment tree, say tree[], where each node stores the sum of squares of the position of the characters in English alphabets in its subtree.
- For Query(“U”, “I”, “X”), define an update function, similar to the update function of sum range queries. Update S[i] = X and then call the update() function to update the segment tree.
- For Query(“S”, “L”, “R”), define a function query(), similar to sum range query and then, print the sum obtained by calling the query() function for the substring {S[L], …., S[R]}.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
struct treeNode {
int square_sum;
};
void buildTree(string s, treeNode* tree,
int start, int end,
int treeNode)
{
if (start == end) {
tree[treeNode].square_sum
= pow (s[start] - 'a' + 1, 2);
return ;
}
int mid = start + ((end - start) / 2);
buildTree(s, tree, start,
mid, 2 * treeNode);
buildTree(s, tree, mid + 1,
end, 1 + 2 * treeNode);
tree[treeNode].square_sum
= tree[(2 * treeNode)].square_sum
+ tree[(2 * treeNode) + 1].square_sum;
}
int querySquareSum(treeNode* tree, int start,
int end, int treeNode,
int l, int r)
{
if ((l > end) || (r < start)) {
return 0;
}
if ((l <= start) && (r >= end)) {
return tree[treeNode].square_sum;
}
int mid = start + ((end - start) / 2);
int X = querySquareSum(tree, start,
mid, 2 * treeNode,
l, r);
int Y = +querySquareSum(tree, mid + 1, end,
1 + 2 * treeNode, l, r);
return X + Y;
}
void updateTree(string s, treeNode* tree,
int start, int end,
int treeNode, int idx, char X)
{
if ((start == end) && (idx == start)) {
s[idx] = X;
tree[treeNode].square_sum
= pow (X - 'a' + 1, 2);
return ;
}
int mid = start + ((end - start) / 2);
if (idx <= mid) {
updateTree(s, tree, start, mid,
(2 * treeNode), idx, X);
}
else {
updateTree(s, tree, mid + 1, end,
(2 * treeNode) + 1, idx, X);
}
tree[treeNode].square_sum
= tree[(2 * treeNode)].square_sum
+ tree[(2 * treeNode) + 1].square_sum;
}
void PerformQuery(string S,
vector<vector<string> > Q)
{
int n = S.size();
treeNode* tree = new treeNode[(4 * n) + 1];
for ( int i = 0; i <= (4 * n); i = i + 1) {
tree[i].square_sum = 0;
}
buildTree(S, tree, 0, n - 1, 1);
for ( int i = 0; i < Q.size(); i++) {
if (Q[i][0] == "S" ) {
int L = stoi(Q[i][1]);
int R = stoi(Q[i][2]);
cout << querySquareSum(tree, 0,
n - 1, 1, L, R)
<< endl;
}
else if (Q[i][0] == "U" ) {
int I = stoi(Q[i][1]);
updateTree(S, tree, 0, n - 1,
1, I, Q[i][2][0]);
}
}
}
int main()
{
string S = "horje" ;
vector<vector<string> > Q = { { "S" , "0" , "2" },
{ "S" , "1" , "2" },
{ "U" , "1" , "a" },
{ "S" , "0" , "2" },
{ "S" , "4" , "5" } };
PerformQuery(S, Q);
}
|
Java
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG{
static class treeNode
{
int square_sum;
treeNode( int square_sum)
{
this .square_sum = square_sum;
}
};
static void buildTree( char s[], treeNode tree[],
int start, int end, int treenode)
{
if (start == end)
{
tree[treenode].square_sum = ( int )Math.pow(
s[start] - 'a' + 1 , 2 );
return ;
}
int mid = start + ((end - start) / 2 );
buildTree(s, tree, start, mid, 2 * treenode);
buildTree(s, tree, mid + 1 , end, 1 + 2 * treenode);
tree[treenode].square_sum = tree[( 2 * treenode)].square_sum +
tree[( 2 * treenode) + 1 ].square_sum;
}
static int querySquareSum(treeNode tree[], int start,
int end, int treenode, int l,
int r)
{
if ((l > end) || (r < start))
{
return 0 ;
}
if ((l <= start) && (r >= end))
{
return tree[treenode].square_sum;
}
int mid = start + ((end - start) / 2 );
int X = querySquareSum(tree, start, mid,
2 * treenode, l, r);
int Y = +querySquareSum(tree, mid + 1 , end,
1 + 2 * treenode, l, r);
return X + Y;
}
static void updateTree( char s[], treeNode tree[],
int start, int end, int treenode,
int idx, char X)
{
if ((start == end) && (idx == start))
{
s[idx] = X;
tree[treenode].square_sum = ( int )Math.pow(
X - 'a' + 1 , 2 );
return ;
}
int mid = start + ((end - start) / 2 );
if (idx <= mid)
{
updateTree(s, tree, start, mid, ( 2 * treenode),
idx, X);
}
else
{
updateTree(s, tree, mid + 1 , end,
( 2 * treenode) + 1 , idx, X);
}
tree[treenode].square_sum = tree[( 2 * treenode)].square_sum +
tree[( 2 * treenode) + 1 ].square_sum;
}
static void PerformQuery(String S, String Q[][])
{
int n = S.length();
treeNode tree[] = new treeNode[( 4 * n) + 1 ];
for ( int i = 0 ; i <= ( 4 * n); i = i + 1 )
{
tree[i] = new treeNode( 0 );
}
char s[] = S.toCharArray();
buildTree(s, tree, 0 , n - 1 , 1 );
for ( int i = 0 ; i < Q.length; i++)
{
if (Q[i][ 0 ] == "S" )
{
int L = Integer.parseInt(Q[i][ 1 ]);
int R = Integer.parseInt(Q[i][ 2 ]);
System.out.println(querySquareSum(
tree, 0 , n - 1 , 1 , L, R));
}
else if (Q[i][ 0 ] == "U" )
{
int I = Integer.parseInt(Q[i][ 1 ]);
updateTree(s, tree, 0 , n - 1 , 1 , I,
Q[i][ 2 ].charAt( 0 ));
}
}
}
public static void main(String[] args)
{
String S = "horje" ;
String Q[][] = { { "S" , "0" , "2" },
{ "S" , "1" , "2" },
{ "U" , "1" , "a" },
{ "S" , "0" , "2" },
{ "S" , "4" , "5" } };
PerformQuery(S, Q);
}
}
|
Python3
class treeNode:
def __init__( self , x):
self .square_sum = x
def buildTree(s, tree, start, end, treeNode):
if (start = = end):
tree[treeNode].square_sum = pow ( ord (s[start]) -
ord ( 'a' ) + 1 , 2 )
return
mid = start + ((end - start) / / 2 )
buildTree(s, tree, start, mid, 2 * treeNode)
buildTree(s, tree, mid + 1 , end,
1 + 2 * treeNode)
tree[treeNode].square_sum = (tree[( 2 * treeNode)].square_sum +
tree[( 2 * treeNode) + 1 ].square_sum)
def querySquareSum(tree, start, end, treeNode, l, r):
if ((l > end) or (r < start)):
return 0
if ((l < = start) and (r > = end)):
return tree[treeNode].square_sum
mid = start + ((end - start) / / 2 )
X = querySquareSum(tree, start, mid,
2 * treeNode, l, r)
Y = + querySquareSum(tree, mid + 1 , end,
1 + 2 * treeNode, l, r)
return X + Y
def updateTree(s, tree, start, end, treeNode, idx, X):
if ((start = = end) and (idx = = start)):
s[idx] = X
tree[treeNode].square_sum = pow ( ord (X) -
ord ( 'a' ) + 1 , 2 )
return
mid = start + ((end - start) / / 2 )
if (idx < = mid):
updateTree(s, tree, start, mid,
( 2 * treeNode), idx, X)
else :
updateTree(s, tree, mid + 1 , end,
( 2 * treeNode) + 1 , idx, X)
tree[treeNode].square_sum = (tree[( 2 * treeNode)].square_sum +
tree[( 2 * treeNode) + 1 ].square_sum)
def PerformQuery(S, Q):
n = len (S)
tree = [treeNode( 0 ) for i in range (( 4 * n) + 1 )]
for i in range ( 4 * n + 1 ):
tree[i].square_sum = 0
buildTree(S, tree, 0 , n - 1 , 1 )
for i in range ( len (Q)):
if (Q[i][ 0 ] = = "S" ):
L = int (Q[i][ 1 ])
R = int (Q[i][ 2 ])
print (querySquareSum(tree, 0 , n - 1 ,
1 , L, R))
elif (Q[i][ 0 ] = = "U" ):
I = int (Q[i][ 1 ])
updateTree(S, tree, 0 , n - 1 ,
1 , I, Q[i][ 2 ][ 0 ])
if __name__ = = '__main__' :
S = "horje"
Q = [ [ "S" , "0" , "2" ],
[ "S" , "1" , "2" ],
[ "U" , "1" , "a" ],
[ "S" , "0" , "2" ],
[ "S" , "4" , "5" ] ]
PerformQuery([i for i in S], Q)
|
C#
using System;
public class treeNode
{
public int square_sum;
public treeNode( int square_sum)
{
this .square_sum = square_sum;
}
};
public class GFG{
static void buildTree( char [] s, treeNode[] tree,
int start, int end, int treenode)
{
if (start == end)
{
tree[treenode].square_sum = ( int )Math.Pow(
s[start] - 'a' + 1, 2);
return ;
}
int mid = start + ((end - start) / 2);
buildTree(s, tree, start, mid, 2 * treenode);
buildTree(s, tree, mid + 1, end, 1 + 2 * treenode);
tree[treenode].square_sum = tree[(2 * treenode)].square_sum +
tree[(2 * treenode) + 1].square_sum;
}
static int querySquareSum(treeNode[] tree, int start,
int end, int treenode, int l,
int r)
{
if ((l > end) || (r < start))
{
return 0;
}
if ((l <= start) && (r >= end))
{
return tree[treenode].square_sum;
}
int mid = start + ((end - start) / 2);
int X = querySquareSum(tree, start, mid,
2 * treenode, l, r);
int Y = +querySquareSum(tree, mid + 1, end,
1 + 2 * treenode, l, r);
return X + Y;
}
static void updateTree( char [] s, treeNode[] tree,
int start, int end, int treenode,
int idx, char X)
{
if ((start == end) && (idx == start))
{
s[idx] = X;
tree[treenode].square_sum = ( int )Math.Pow(
X - 'a' + 1, 2);
return ;
}
int mid = start + ((end - start) / 2);
if (idx <= mid)
{
updateTree(s, tree, start, mid, (2 * treenode),
idx, X);
}
else
{
updateTree(s, tree, mid + 1, end,
(2 * treenode) + 1, idx, X);
}
tree[treenode].square_sum = tree[(2 * treenode)].square_sum +
tree[(2 * treenode) + 1].square_sum;
}
static void PerformQuery(String S, String[,] Q)
{
int n = S.Length;
treeNode[] tree = new treeNode[(4 * n) + 1];
for ( int i = 0; i <= (4 * n); i = i + 1)
{
tree[i] = new treeNode(0);
}
char [] s = S.ToCharArray();
buildTree(s, tree, 0, n - 1, 1);
for ( int i = 0; i < Q.GetLength(0); i++)
{
if (Q[i,0] == "S" )
{
int L = Int32.Parse(Q[i,1]);
int R = Int32.Parse(Q[i,2]);
Console.WriteLine(querySquareSum(
tree, 0, n - 1, 1, L, R));
}
else if (Q[i,0] == "U" )
{
int I = Int32.Parse(Q[i,1]);
updateTree(s, tree, 0, n - 1, 1, I,
Q[i,2][0]);
}
}
}
static public void Main (){
string S = "horje" ;
string [,] Q = { { "S" , "0" , "2" },
{ "S" , "1" , "2" },
{ "U" , "1" , "a" },
{ "S" , "0" , "2" },
{ "S" , "4" , "5" } };
PerformQuery(S, Q);
}
}
|
Javascript
<script>
class treeNode
{
constructor( square_sum)
{
this .square_sum = square_sum;
}
}
function buildTree(s,tree,start,end,treenode)
{
if (start == end)
{
tree[treenode].square_sum = Math.pow(
s[start].charCodeAt(0) - 'a' .charCodeAt(0) + 1, 2);
return ;
}
let mid = start + Math.floor((end - start) / 2);
buildTree(s, tree, start, mid, 2 * treenode);
buildTree(s, tree, mid + 1, end, 1 + 2 * treenode);
tree[treenode].square_sum = tree[(2 * treenode)].square_sum +
tree[(2 * treenode) + 1].square_sum;
}
function querySquareSum(tree,start,end,treenode,l,r)
{
if ((l > end) || (r < start))
{
return 0;
}
if ((l <= start) && (r >= end))
{
return tree[treenode].square_sum;
}
let mid = start + Math.floor((end - start) / 2);
let X = querySquareSum(tree, start, mid,
2 * treenode, l, r);
let Y = +querySquareSum(tree, mid + 1, end,
1 + 2 * treenode, l, r);
return X + Y;
}
function updateTree(s,tree,start,end,treenode,idx,X)
{
if ((start == end) && (idx == start))
{
s[idx] = X;
tree[treenode].square_sum = Math.pow(
X.charCodeAt(0) - 'a' .charCodeAt(0) + 1, 2);
return ;
}
let mid = start + Math.floor((end - start) / 2);
if (idx <= mid)
{
updateTree(s, tree, start, mid, (2 * treenode),
idx, X);
}
else
{
updateTree(s, tree, mid + 1, end,
(2 * treenode) + 1, idx, X);
}
tree[treenode].square_sum = tree[(2 * treenode)].square_sum +
tree[(2 * treenode) + 1].square_sum;
}
function PerformQuery(S,Q)
{
let n = S.length;
let tree = new Array((4 * n) + 1);
for (let i = 0; i <= (4 * n); i = i + 1)
{
tree[i] = new treeNode(0);
}
let s = S.split( "" );
buildTree(s, tree, 0, n - 1, 1);
for (let i = 0; i < Q.length; i++)
{
if (Q[i][0] == "S" )
{
let L = parseInt(Q[i][1]);
let R = parseInt(Q[i][2]);
document.write(querySquareSum(
tree, 0, n - 1, 1, L, R)+ "<br>" );
}
else if (Q[i][0] == "U" )
{
let I = parseInt(Q[i][1]);
updateTree(s, tree, 0, n - 1, 1, I,
Q[i][2][0]);
}
}
}
let S = "horje" ;
let Q=[[ "S" , "0" , "2" ],
[ "S" , "1" , "2" ],
[ "U" , "1" , "a" ],
[ "S" , "0" , "2" ],
[ "S" , "4" , "5" ]]
PerformQuery(S, Q);
</script>
|
Time Complexity: O((N + M) * log N) Auxiliary Space: O(N)
|