namespace CodeJam.Sample.DataStructures
{
using System;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Implement the Binary Indexed Tree data structure.
/// Simulation of an array of N elements for which the operation of incrementing x[i] by j
/// and the operation give x[1]+...+x[i] are both O(log N).
/// </summary>
public class BinaryIndexedTree
{
/// <summary>
/// The number of elements in the array we are simulating.
/// </summary>
private int numberOfElements;
/// <summary>
/// The contents of the internal array.
/// </summary>
private int[] contents;
/// <summary>
/// Initializes a new instance of the <see cref="CodeJam.Sample.DataStructures.BinaryIndexedTree"/> class.
/// </summary>
/// <param name="n">Number of elements in the array.</param>
public BinaryIndexedTree(int n)
{
this.numberOfElements = n;
this.contents = new int[n + 1];
}
/// <summary>
/// Gets or sets the element at the specified index in the array.
/// </summary>
/// <returns>The element at the index.</returns>
/// <param name="index">1-Based Index at which to get or set.</param>
public int this[int index]
{
get { return this.Accumulate(index) - this.Accumulate(index - 1); }
set { this.Increment(index, value - this[index]); }
}
/// <summary>
/// Increment an element of the simulated array by a certain amount.
/// </summary>
/// <param name="index">1-Based index of simulated array.</param>
/// <param name="amount">Amount by which to increment.</param>
public void Increment(int index, int amount)
{
while (index <= this.numberOfElements)
{
this.contents[index] += amount;
index += this.LeastSignificantBit(index);
}
}
/// <summary>
/// Return the sum of all of the elements in the array up to and including the given index
/// </summary>
/// <returns>The sum of all elements up to the given index</returns>
/// <param name="index">1-Based index up to which to accumulate.</param>
public int Accumulate(int index)
{
int accumulation = 0;
while (index > 0)
{
accumulation += this.contents[index];
index -= this.LeastSignificantBit(index);
}
return accumulation;
}
/// <summary>
/// Returns the least significant bit of an integer.
/// </summary>
/// <returns>The least significant bit.</returns>
/// <param name="n">Input integer.</param>
private int LeastSignificantBit(int n)
{
return n & (-n);
}
}
/// <summary>
/// A test class for running on ideone
/// </summary>
public class Test
{
/// <summary>
/// Solve the problem, using the Binary Indexed Tree data structure.
/// </summary>
public static void Main()
{
int numberOfCases = GetInt();
for (int caseIndex = 1; caseIndex <= numberOfCases; ++caseIndex)
{
var parameters = GetInts();
int numberOfStudents = parameters[0];
int numberOfChocolates = parameters[1];
/* We are going to use a BinaryIndexedTree to simulate an array x[1], ..., x[N]
* where student i has x[1]+...+x[i] chocolates.
*
* Then we can find out how many chocolates student i has by calling Accumulate(i) (O(log N) time)
* and we can give K chocolates to students i, i+1, ..., j by calling:
* Increment(i, K)
* Increment(j+1, -K)
*
* Note our BinaryIndexedTree uses 1-indexed indices, and the problem uses 0-indexed indices, so we will have to
* add 1 to the student indices we get.
*/
var bit = new BinaryIndexedTree(numberOfStudents);
for (int chocolateIndex = 0; chocolateIndex < numberOfChocolates; ++chocolateIndex)
{
parameters = GetInts();
int fromStudent = parameters[0];
int toStudent = parameters[1];
int chocolateGift = parameters[2];
bit.Increment(fromStudent + 1, chocolateGift);
bit.Increment(toStudent + 2, -chocolateGift);
}
int numberOfFriends = GetInt();
for (int friendIndex = 0; friendIndex < numberOfFriends; ++friendIndex)
{
int friendLocation = GetInt();
Console.WriteLine(bit.Accumulate(friendLocation + 1));
}
}
}
/// <summary>
/// Read a single integer from stdin
/// </summary>
/// <returns>The read integer.</returns>
private static int GetInt()
{
return int.Parse(Console.ReadLine());
}
/// <summary>
/// Read a line of space separated integers from stdin
/// </summary>
/// <returns>The read integers.</returns>
private static List<int> GetInts()
{
return Console.ReadLine().Split(' ').Select(_ => int.Parse(_)).ToList();
}
}
}