Cod sursa(job #3233340)

Utilizator alex_0747Gheorghica Alexandru alex_0747 Data 2 iunie 2024 23:46:32
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.51 kb
#include <iostream>
#include <fstream>
#include <vector>
#define INF 2000000000
using  namespace std;

class ArboreMax
{
protected:
	int *aint;
	int n;
public:

	ArboreMax(int n) { Init(n); }
	ArboreMax(int a[], int n) { Init(n); Build(a, 1, 1, n); }
	
	virtual void Init(int n)
	{
		this->n = n;
		aint = new int[4 * n + 1];
		for (int i = 0; i <= 4 * n; i++)
			aint[i] = InitInt();
	}

	void Build(int a[], int nod, int l, int r)
	{
		if (l == r)
		{
			aint[nod] = a[l];
			return;
		}
		int mid = (l + r) / 2;
		Build(a, 2 * nod, l, mid);
		Build(a, 2 * nod + 1, mid + 1, r);
		aint[nod] = Merge(aint[2 * nod], aint[2 * nod + 1]);
	}

	virtual int Merge(int a, int b)
	{
		return max(a, b);
	}

	virtual int InitInt() { return -2e9; }

	virtual void Update(int nod, int l, int r, int p, int x)
	{
		if (r < p || l > p) return;
		if (l == r)
		{
			aint[nod] = x;
			return;
		}
		int mid = (l + r) / 2;
		Update(2 * nod, l, mid, p, x);
		Update(2 * nod + 1, mid + 1, r, p, x);
		aint[nod] = Merge(aint[2 * nod], aint[2 * nod + 1]);
	}

	int Query(int nod, int l, int r, int start, int end)
	{
		if (r < start || l > end) return InitInt();
		if (start <= l && r <= end) return aint[nod];
		int mid = (l + r) / 2;
		int q1 = Query(2 * nod, l, mid, start, end);
		int q2 = Query(2 * nod + 1, mid + 1, r, start, end);
		return Merge(q1, q2);
	}
};

class ArboreMin : public ArboreMax
{
public:

	ArboreMin(int n) : ArboreMax(n) {}
	ArboreMin(int a[], int n) : ArboreMax(a, n) {}

	virtual int InitInt() { return 2e9; }

	virtual int Merge(int a, int b)
	{
		return min(a, b);
	}

};

class ArboreSum : public ArboreMax
{
public:
	ArboreSum(int n) : ArboreMax(n) {}
	ArboreSum(int a[], int n) : ArboreMax(a, n) {}

	virtual int InitInt() { return 0; }

	virtual int Merge(int a, int b)
	{
		return a + b;
	}
};

class ArboreGCD : public ArboreMax
{
	ArboreGCD(int n) : ArboreMax(n) {}
	ArboreGCD(int a[], int n) : ArboreMax(a, n) {}

	virtual int InitInt() { return 0; }

	virtual int Merge(int a, int b)
	{
		if (b == 0) return a;
		return Merge(b, a % b);
	}
};

class ArboreMinLazy : ArboreMin
{
protected:
	int* lazy;
public:

	int InitInt() { return 0; }

	ArboreMinLazy(int n) : ArboreMin(n)
	{
		lazy = new int[4 * n + 1];
		for (int i = 0; i <= 4 * n; i++)
			lazy[i] = 0;
	}
	ArboreMinLazy(int a[], int n) : ArboreMin(a, n)
	{
		lazy = new int[4 * n + 1];
		for (int i = 0; i <= 4 * n; i++)
			lazy[i] = 0;
	}

	virtual void Update(int nod, int l, int r, int p, int x)
	{
		if (lazy[nod] != 0)
		{
			aint[nod] += lazy[nod];
			if (l != r)
			{
				lazy[2 * nod] += lazy[nod];
				lazy[2 * nod + 1] += lazy[nod];
			}
			lazy[nod] = 0;
		}
		if (r < p || l > p) return;
		if (l == r)
		{
			aint[nod] = x;
			return;
		}
		int mid = (l + r) / 2;
		Update(2 * nod, l, mid, p, x);
		Update(2 * nod + 1, mid + 1, r, p, x);
	}

	virtual void UpdateLazy(int nod, int l, int r, int start, int end, int val)
	{
		if (lazy[nod] != 0)
		{
			aint[nod] += lazy[nod];
			if (l != r)
			{
				lazy[2 * nod] += lazy[nod];
				lazy[2 * nod + 1] += lazy[nod];
			}
			lazy[nod] = 0;
		}
		if (r < start || l > end) return;
		if (start <= l && r <= end)
		{
			aint[nod] = val;
			if (l != r)
			{
				lazy[2 * nod] += val;
				lazy[2 * nod + 1] += val;
			}
			return;
		}
		int mid = (l + r) / 2;
		UpdateLazy(2 * nod, l, mid, start, end, val);
		UpdateLazy(2 * nod + 1, mid + 1, r, start, end, val);
		aint[nod] = Merge(aint[2 * nod], aint[2 * nod + 1]);
	}

	virtual int Query(int nod, int l, int r, int start, int end)
	{
		if (lazy[nod] != 0)
		{
			aint[nod] += lazy[nod];
			if (l != r)
			{
				lazy[2 * nod] += lazy[nod];
				lazy[2 * nod + 1] += lazy[nod];
			}
			lazy[nod] = 0;
		}
		if (r < start || l > end) return InitInt();
		if (start <= l && r <= end) return aint[nod];
		int mid = (l + r) / 2;
		int q1 = Query(2 * nod, l, mid, start, end);
		int q2 = Query(2 * nod + 1, mid, r, start, end);
		return Merge(q1, q2);
	}
};

/**
Problema Arbori De Intervale din arhiva educationala infoarena
*/
class arbint
{
private:
	int a[100005], n;
public:
	void Sol()
	{
		ifstream fin("arbint.in");
		ofstream fout("arbint.out");
		int i, q, op, x, y;
		fin >> n >> q;
		for (i = 1; i <= n; i++)
			fin >> a[i];
		ArboreMax aint(a, n);
		while (q--)
		{
			fin >> op >> x >> y;
			if (op == 0)
				fout << aint.Query(1, 1, n, x, y) << "\n";
			else
				aint.Update(1, 1, n, x, y);
		}
	}
};

/**
Problema SubtreeQueries de pe cses.fi
- liniarizarea arborelui + arbori de intervale

*** trebuie long long ca solutia sa fie corecta
* 
*/
class SubtreeQueries
{
private:
	vector <int> L[200005];
	int a[200005], tin[200005], tout[200005], t, n;
public:
	void DFS(int k, int ant)
	{
		tin[k] = ++t;
		for (int i : L[k])
			if (i != ant)
				DFS(i, k);
		tout[k] = t;
	}
	void Sol()
	{
		int i, q, op, x, y;
		cin >> n >> q;
		for (i = 1; i <= n; i++)
			cin >> a[i];
		for (i = 1; i < n; i++)
		{
			cin >> x >> y;
			L[x].push_back(y);
			L[y].push_back(x);
		}

		ArboreSum aint(n);
		DFS(1, 0);
		for (i = 1; i <= n; i++)
			aint.Update(1, 1, n, tin[i], a[i]);
		while (q--)
		{
			cin >> op >> x;
			if (op == 1)
			{
				cin >> y;
				aint.Update(1, 1, n, tin[x], y);
				a[x] = y;
			}
			else
				cout << aint.Query(1, 1, n, tin[x], tout[x]) << "\n";
		}
	}
};

SubtreeQueries s;
arbint a;


int main()
{
	a.Sol();
	//s.Sol();
	return 0;
}