Cod sursa(job #2615015)

Utilizator MarcGrecMarc Grec MarcGrec Data 13 mai 2020 14:42:13
Problema Arbori indexati binar Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.15 kb
#define MAX_N 100000
#define LOG_MAX_N 16
 
#define FTH(x) (x >> 1)
#define LFT_SON(x) (x << 1)
#define RIG_SON(x) (LFT_SON(x) + 1)
 
#include <iostream>
#include <fstream>
using namespace std;
 
ifstream fin("aib.in");
ofstream fout("aib.out");
 
struct nodeinfo
{	
	int a, b, sum;
};
 
int n, m, A[MAX_N + 1], I[MAX_N + 1];
nodeinfo G[1 << (LOG_MAX_N + 2)];
 
void ConstructTree(int node, int a, int b);
 
void Update(int index, int val);
 
int SumRange(int a, int b);
void Query(int node, int a, int b, int& sum);
 
int MinK(int sum);
void QueryK(int node, int sum, int& k);
 
int main()
{
	fin >> n >> m;
	
	for (int i = 1; i <= n; ++i)
	{
		fin >> A[i];
	}
	
	ConstructTree(1, 1, n);
	
	for (int i = 1, c, a, b; i <= m; ++i)
	{
		fin >> c;
		
		if (c == 0)
		{
			fin >> a >> b;
			Update(a, b);
		}
		
		if (c == 1)
		{
			fin >> a >> b;
			fout << SumRange(a, b) << '\n';
		}
		
		if (c == 2)
		{
			fin >> a;
			
			fout << MinK(a) << '\n';
		}
	}
	
	fin.close();
	fout.close();
	return 0;
}
 
void ConstructTree(int node, int a, int b)
{	
	G[node] = { a, b };
	
	if (a == b)
	{
		I[a]        = node;
		G[node].sum = A[a];
	}
	else
	{
		const int mid = (a + b) / 2;
		ConstructTree(LFT_SON(node), a, mid);
		ConstructTree(RIG_SON(node), mid + 1, b);
		
		G[node].sum = G[LFT_SON(node)].sum + G[RIG_SON(node)].sum;
	}
}
 
void Update(int index, int val)
{
	int node    = I[index];
	G[node].sum += val;
	node        = FTH(node);
	
	int sum_old;
	while (node != 0)
	{
		sum_old     = G[node].sum;
		G[node].sum = G[LFT_SON(node)].sum + G[RIG_SON(node)].sum;
		node        = (sum_old != G[node].sum) ? FTH(node) : 0;
	}
}
 
int SumRange(int a, int b)
{
	if (a == b)
	{
		return G[I[a]].sum;
	}
	else
	{
		int sum = 0;
	
		Query(I[a], a, b, sum);
	
		return sum;
	}
}
 
void QueryDown(int node, int a, int b, int& sum)
{
	if (G[node].b == b)
	{
		sum += G[node].sum;
		return;
	}
	
	if (G[LFT_SON(node)].b >= b)
	{
		QueryDown(LFT_SON(node), a, b, sum);
	}
	else
	{
		sum += G[LFT_SON(node)].sum;
		QueryDown(RIG_SON(node), a, b, sum);
	}
}
 
void Query(int node, int a, int b, int& sum)
{
	if (G[node].b < b)
	{
		if (RIG_SON(FTH(node)) == node)
		{
			sum -= G[node].sum;
		}
		
		if (G[node].a != G[node].b)
		{
			sum += G[RIG_SON(node)].sum;
		}
		else
		{
			sum += G[node].sum;
		}
		
		Query(FTH(node), a, b, sum);
	}
	else
	{	
		QueryDown(RIG_SON(node), a, b, sum);
	}
}
 
int MinK(int sum)
{
	int k;
	
	QueryK(I[1], sum, k);
	
	return k;
}
 
void QueryK(int node, int sum, int& k)
{
	while (true)
	{
		if (G[node].sum < sum)
		{
			if (node != 1)
			{
				node = FTH(node);
			}
			else
			{
				k = -1;
				return;
			}
		}
		else
		{
			if (G[node].sum == sum)
			{
				k = G[node].b;
				return;
			}
			
			if (G[node].a != G[node].b)
			{
				const int sum_lft = G[node].sum - G[RIG_SON(node)].sum;
				if (sum_lft >= sum)
				{
					node = LFT_SON(node);
				}
				else
				{
					sum -= sum_lft;
					node = RIG_SON(node);
				}
			}
			else
			{
				k = -1;
				return;
			}
		}
	}
}