using System;
public class treeNode
{
public int square_sum;
public treeNode(int square_sum)
{
this.square_sum = square_sum;
}
};
public class GFG{
// Function to construct the Segment Tree
static void buildTree(char[] s, treeNode[] tree,
int start, int end, int treenode)
{
// If start and end are equal
if (start == end)
{
// Assign squares of positions
// of the characters
tree[treenode].square_sum = (int)Math.Pow(
s[start] - 'a' + 1, 2);
return;
}
// Stores the mid value of
// the range [start, end]
int mid = start + ((end - start) / 2);
// Recursive call to left subtree
buildTree(s, tree, start, mid, 2 * treenode);
// Recursive call to right subtree
buildTree(s, tree, mid + 1, end, 1 + 2 * treenode);
// Update the current node
tree[treenode].square_sum = tree[(2 * treenode)].square_sum +
tree[(2 * treenode) + 1].square_sum;
}
// Function to perform the queries of type 2
static int querySquareSum(treeNode[] tree, int start,
int end, int treenode, int l,
int r)
{
// No overlap
if ((l > end) || (r < start))
{
return 0;
}
// If l <= start and r >= end
if ((l <= start) && (r >= end))
{
// Return the value of treeNode
return tree[treenode].square_sum;
}
// Calculate middle of the range [start, end]
int mid = start + ((end - start) / 2);
// Function call to left subtree
int X = querySquareSum(tree, start, mid,
2 * treenode, l, r);
// Function call to right subtree
int Y = +querySquareSum(tree, mid + 1, end,
1 + 2 * treenode, l, r);
// Return the sum of X and Y
return X + Y;
}
// Function to perform update
// queries on a Segment Tree
static void updateTree(char[] s, treeNode[] tree,
int start, int end, int treenode,
int idx, char X)
{
// If start is equal to end
// and idx is equal to start
if ((start == end) && (idx == start))
{
// Base Case
s[idx] = X;
tree[treenode].square_sum = (int)Math.Pow(
X - 'a' + 1, 2);
return;
}
// Calculate middle of the range [start, end]
int mid = start + ((end - start) / 2);
// If idx <= mid
if (idx <= mid)
{
// Function call to left subtree
updateTree(s, tree, start, mid, (2 * treenode),
idx, X);
}
// Otherwise
else
{
// Function call to the right subtree
updateTree(s, tree, mid + 1, end,
(2 * treenode) + 1, idx, X);
}
// Update the current node
tree[treenode].square_sum = tree[(2 * treenode)].square_sum +
tree[(2 * treenode) + 1].square_sum;
}
// Function to perform the given queries
static void PerformQuery(String S, String[,] Q)
{
int n = S.Length;
// Stores the segment tree
treeNode[] tree = new treeNode[(4 * n) + 1];
// Traverse the segment tree
for(int i = 0; i <= (4 * n); i = i + 1)
{
// Assign 0 to each node
tree[i] = new treeNode(0);
}
char[] s = S.ToCharArray();
// Builds segment tree
buildTree(s, tree, 0, n - 1, 1);
// Traverse the query array Q[][]
for(int i = 0; i < Q.GetLength(0); i++)
{
// If query is of type S
if (Q[i,0] == "S")
{
// Stores the left boundary
int L = Int32.Parse(Q[i,1]);
// Stores the right boundary
int R = Int32.Parse(Q[i,2]);
// Prints the sum of squares of the
// alphabetic positions of the characters
Console.WriteLine(querySquareSum(
tree, 0, n - 1, 1, L, R));
}
// Otherwise
else if (Q[i,0] == "U")
{
// Stores the index of the
// character to be updated
int I = Int32.Parse(Q[i,1]);
// Update the segment tree
updateTree(s, tree, 0, n - 1, 1, I,
Q[i,2][0]);
}
}
}
// Driver Code
static public void Main (){
// Input
string S = "geeksforgeeks";
string[,] Q = { { "S", "0", "2" },
{ "S", "1", "2" },
{ "U", "1", "a" },
{ "S", "0", "2" },
{ "S", "4", "5" } };
// Function call
PerformQuery(S, Q);
}
}
// This code is contributed by unknown2108.