// C# code to implement the approach
using System;
class GFG {
// Function to get the middle index
// from corner indices.
static int getMiddleValue(int low, int high)
{
return low + (high - low) / 2;
}
// A recursive function to get the sum of values
// in the given range of the array.
// st --> Pointer to segment tree
// node --> Index of current node in the segment tree.
// low & high --> Starting and ending indices
// of the segment represented by current node.
// L & R --> Starting and ending indices of query range
static int getSumUtil(int[] st, int low, int high,
int L, int R, int node)
{
// If segment of this node is a part of given range
// then return the sum of the segment
if (L <= low && R >= high)
return st[node];
// If segment of this node is outside the given
// range
if (high < L || low > R)
return 0;
// If a part of this segment
// overlaps with the given range
int mid = getMiddleValue(low, high);
return getSumUtil(st, low, mid, L, R, 2 * node + 1)
+ getSumUtil(st, mid + 1, high, L, R,
2 * node + 2);
}
// Recursive function to update the nodes
// which have the given index in their range.
static void updateValueUtil(int[] st, int low, int high,
int i, int diff, int node)
{
// If the input index lies outside
// the range of this segment
if (i < low || i > high)
return;
// If the input index is in range of this node,
// then update the value of the node
// and its children
st[node] = st[node] + diff;
if (high != low) {
int mid = getMiddleValue(low, high);
updateValueUtil(st, low, mid, i, diff,
2 * node + 1);
updateValueUtil(st, mid + 1, high, i, diff,
2 * node + 2);
}
}
// Function to update a value in input array
// and segment tree.
// It uses updateValueUtil() to update
// the value in segment tree
static void updateValue(int[] arr, int[] st, int n,
int i, int new_val)
{
// Get the difference between new and old value
int diff = new_val - arr[i];
// Update the value in array
arr[i] = new_val;
// Update the values of nodes in segment tree
updateValueUtil(st, 0, n - 1, i, diff, 0);
}
// Return sum of elements in range from index L (query
// start) to R (query end). It mainly uses getSumUtil()
static int getSum(int[] st, int n, int L, int R)
{
return getSumUtil(st, 0, n - 1, L, R, 0);
}
// Recursive function that constructs Segment Tree
// for array[low..high].
static int buildSegTreeUtil(int[] arr, int low,
int high, int[] st,
int node)
{
// If there is one element in array,
// store it in current node of segment
if (low == high) {
st[node] = arr[low];
return arr[low];
}
// 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 = getMiddleValue(low, high);
st[node] = buildSegTreeUtil(arr, low, mid, st,
node * 2 + 1)
+ buildSegTreeUtil(arr, mid + 1, high,
st, node * 2 + 2);
return st[node];
}
// Function to construct segment tree from given array.
// This function allocates memory for segment tree and
// calls buildSegTreeUtil() to fill the allocated memory
static int[] buildSegTree(int[] arr, int n)
{
// 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];
// Fill the allocated memory st
buildSegTreeUtil(arr, 0, n - 1, st, 0);
// Return the constructed segment tree
return st;
}
// Function to check if the subarray is permutation or not
static void findPermutation(int[] arr, int N, int[,] Q,
int M)
{
// Build segment tree from given array
int[] st = buildSegTree(arr, N);
// Traverse the given queries
for (int i = 0; i < M; i++) {
// Query type for querying
int queryType = Q[i,0];
// If query is of type 1
if (queryType == 1) {
// Position and value for update
int pos = Q[i,1], value = Q[i,2];
// Update: set arr[pos] = value and update
// corresponding segment tree nodes
updateValue(arr, st, N, pos, value);
}
else {
// Stores range L to R for
// type 2 query
int L = Q[i,1], R = Q[i,2];
// Size variable stores size of
// [L, R] range
int size = R - L + 1;
// Stores total from 1 to size of
// range [L, R]
int total_From_1_To_Size
= size * (size + 1) / 2;
// Print sum of values in array
// from index L to R
int total_From_L_To_R = getSum(st, N, L, R);
// If total from 1 to size is equal
// to total from L to R then print yes
if (total_From_L_To_R
== total_From_1_To_Size) {
Console. WriteLine("YES");
}
else {
Console. WriteLine("NO");
}
}
}
}
public static void Main(string[] args)
{
int[] arr = { 6, 4, 1, 2, 3, 8, 10 };
int N = arr.Length;
int[,] Q = { { 2, 2, 4 }, { 1, 2, 9 }, { 2, 2, 4 },
{ 1, 2, 1 }, { 2, 0, 4 }, { 1, 0, 5 },
{ 2, 0, 4 } };
int M = Q.GetLength(0);
// Function call
findPermutation(arr, N, Q, M);
}
}
// This code is contributed by Aman Kumar