// C# program to count the number of inversion
// Tuples in a 2D matrix
using System;
using System.Collections.Generic;
class GFG
{
// for simplicity, we are taking N as 4
static int N = 4;
// Function to update a 2D BIT. It updates the
// value of bit[l, r] by adding val to bit[l, r]
static void update(int l, int r, int val, int[,] bit)
{
for (int x = l; x <= N; x += (x & -x))
for (int j = r; j <= N; j += j & -j)
bit[x, j] += val;
}
// function to find cumulative sum upto
// index (l, r) in the 2D BIT
static int query(int l, int r, int[,] bit)
{
int ret = 0;
for (int x = l; x > 0; x -= (x & -x))
for (int j = r; j > 0; j -= (j & -j))
ret += bit[x, j];
return ret;
}
// function to count and return the number
// of inversion Tuples in the matrix
static int countInversionTuples(int[,] mat)
{
// the 2D bit array and initialize it with 0.
int[, ] bit = new int[N + 1, N +1];
for (int x = 0; x <= N; x++)
for (int y = 0; y <= N; y++)
bit[x, y] = 0;
// v will store the tuple (-mat[i, j], i, j)
List<Tuple<int, Tuple<int, int> > > v = new List<Tuple<int, Tuple<int, int> > >();
// store the tuples in the vector v
for (int x = 0; x < N; ++x)
for (int j = 0; j < N; ++j)
// Note that we are not using the Tuple
// (0, 0) because BIT update and query
// operations are not done on index 0
v.Add(Tuple.Create(-mat[x, j],
Tuple.Create(x+1, j+1)));
// sort the vector v according to the
// first element of the tuple, i.e., -mat[i, j]
v.Sort();
// inv_Tuple_cnt will store the number of
// inversion Tuples
int inv_Tuple_cnt = 0;
// traverse all the tuples of vector v
int i = 0;
while (i < v.Count)
{
int curr = i;
// 'Tuples' will store the position of each element,
// i.e., the Tuple (i, j) of each tuple of the vector v
List<Tuple<int, int>> Tuples = new List<Tuple<int, int>>();
// consider the current tuple in v and all its
// adjacent tuples whose first value, i.e., the
// value of –mat[i, j] is same
while (curr < v.Count &&
(v[curr].Item1 == v[i].Item1))
{
// push the position of the current element in 'Tuples'
Tuples.Add(Tuple.Create(v[curr].Item2.Item1,
v[curr].Item2.Item2));
// add the number of elements which are
// less than the current element and lie on the right
// side in the vector v
inv_Tuple_cnt += query(v[curr].Item2.Item1,
v[curr].Item2.Item2, bit);
curr++;
}
// traverse the 'Tuples' vector
foreach (var it in Tuples)
{
int x = it.Item1;
int y = it.Item2;
// update the position (x, y) by 1
update(x, y, 1, bit);
}
i = curr;
}
return inv_Tuple_cnt;
}
// Driver program
public static void Main(string[] args)
{
int[, ] mat = { { 4, 7, 2, 9 },
{ 6, 4, 1, 7 },
{ 5, 3, 8, 1 },
{ 3, 2, 5, 6 } };
int inv_Tuple_cnt = countInversionTuples(mat);
Console.WriteLine( "The number of inversion Tuples are : " + inv_Tuple_cnt);
}
}
// This code is contributed by phasing17.