Cod sursa(job #1883668)

Utilizator Impaler_009Mihai Nitu Impaler_009 Data 18 februarie 2017 09:57:29
Problema Arbori de intervale Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 8.14 kb
#include <iostream>
#include <vector>

namespace segment_tree {

template<typename T>
class SegmentTree;

class TravelState {
 public:
	int index, left, right, mid;

	TravelState(int index, int left, int right) : index(index), left(left), 
	right(right), mid((left + right)>>1) {}

	inline bool isLeaf() {
		return left == right;
	}

	inline int now() {
		return index;
	}

	inline int leftSon() {
		return index<<1;
	}

	inline int rightSon() {
		return index<<1^1;
	}

	inline TravelState goLeft() {
		return TravelState(leftSon(), left, mid);
	}

	inline TravelState goRight() {
		return TravelState(rightSon(), mid+1, right);
	}
};


template<typename T>
class BaseOp {
 public:
	SegmentTree<T>* segTree;

	BaseOp() : segTree(NULL) {}

	void bind(SegmentTree<T>* segTree) {
		this->segTree = segTree;
	}

	void unbind() {
		segTree = NULL;
	}

	virtual bool shouldStop(TravelState& s) {
		return s.isLeaf();
	}

	virtual bool shouldGoLeft(TravelState& s) {
		return true;
	}

	virtual bool shouldGoRight(TravelState& s) {
		return true;
	}

	virtual void before() {}

	virtual void stopping(TravelState& s) {}

	virtual void going(TravelState& s) {}

	virtual void returning(TravelState& s) {}

	virtual void after() {}
};

template<typename T>
class Build : public BaseOp<T> {
  public:
  	virtual bool shouldStop(TravelState& s) {
		return s.isLeaf();
	}

	virtual bool shouldGoLeft(TravelState& s) {
		return true;
	}

	virtual bool shouldGoRight(TravelState& s) {
		return true;
	}

	virtual void returning(TravelState& s) {
		this->segTree->recalculate((*this->segTree).v[s.now()], (*this->segTree).v[s.leftSon()], 
			(*this->segTree).v[s.rightSon()]);
	}
};

template<typename T>
class PointOp : public BaseOp<T> {
  public:
	int pos;

	PointOp(int pos) : pos(pos) {}

	virtual bool shouldGoLeft(TravelState& s) {
		return (pos <= s.mid);
	}

	virtual bool shouldGoRight(TravelState& s) {
		return (pos > s.mid);
	}
};

template<typename T>
class RangeOp : public BaseOp<T> {
  public:
	int left, right;

	RangeOp(int left, int right) : left(left), right(right) {}

	virtual bool shouldStop(TravelState& s) {
		return (left <= s.left && s.right <= right);
	}

	virtual bool shouldGoLeft(TravelState& s) {
		return (left <= s.mid);
	}

	virtual bool shouldGoRight(TravelState& s) {
		return (right > s.mid);
	}
};

template<typename T, typename U>
class PointUpdate : public PointOp<T> {
  public:
	U upd;
	PointUpdate(int pos, U upd) : PointOp<T>(pos), upd(upd) {}

	virtual void apply(TravelState& s, U& updater) {}

	virtual void stopping(TravelState& s) {
		apply(s, upd);
	}

	virtual void returning(TravelState& s) {
		this->segTree->recalculate((*this->segTree).v[s.now()], (*this->segTree).v[s.leftSon()], 
			(*this->segTree).v[s.rightSon()]);
	}
};

// Type T needs to have fields value and lazy.
// L must be the type of T.lazy.
// Type W from apply will be either T.lazy or U.
template<typename T, typename U, typename L>
class LazyRangeUpdate : public RangeOp<T> {
  public:
	U upd;
	LazyRangeUpdate(int left, int right, U upd) : RangeOp<T>(left, right), upd(upd) {}

	virtual void apply(TravelState& s, U& updater) {}

	virtual void apply(TravelState& s, L& updater) {}

	virtual void unloadLazy(TravelState& s) {
		auto ls = s.leftSon();
		apply(ls, (*this->segTree).v[s.now()].lazy);
		auto rs = s.rightSon();
		apply(rs, (*this->segTree).v[s.now()].lazy);
	}

	virtual void stopping(TravelState& s) {
		apply(s, upd);
	}

	virtual void going(TravelState& s) {
		unloadLazy(s);
	}

	virtual void returning(TravelState& s) {
		this->segTree->recalculate((*this->segTree).v[s.now()], (*this->segTree).v[s.leftSon()], 
			(*this->segTree).v[s.rightSon()]);
	}
};

// Define operator += on T.
template<typename T>
class SumQuery : public RangeOp<T> {
  public:
	T result;
	SumQuery(int left, int right, T init) : 
	RangeOp<T>(left, right), result(init) {}

	virtual void stopping(TravelState& s) {
		std::cout << s.left << " " << s.right << "\n";
		result += (*this->segTree).v[s.now()];
	}
};

// Define operator > on T.
template<typename T>
class MaxRangeQuery : public RangeOp<T> {
  public:
	T result;
	MaxRangeQuery(int left, int right, T init) : 
	RangeOp<T>(left, right), result(init) {}

	virtual void stopping(TravelState& s) {
		if ((*this->segTree).v[s.now()] > result) {
			result = (*this->segTree).v[s.now()];
		}
	}
};

// Define operator < on T.
template<typename T>
class MinRangeQuery : public RangeOp<T> {
  public:
	T result;
	MinRangeQuery(int left, int right, const T& init) : 
	RangeOp<T>(left, right), result(init) {}

	virtual void stopping(TravelState& s) {
		if ((*this->segTree).v[s.now()] < result) {
			result = (*this->segTree).v[s.now()];
		}
	}
};

// Define operator = between T and U.
template<typename T, typename U>
class PointReplace : public PointUpdate<T, U> {
  public:
	PointReplace(int pos, const U& upd) : PointUpdate<T, U>(pos, upd) {}

	virtual void apply(TravelState& s, U& updater) {
		(*this->segTree).v[s.now()] = updater;
	}
};

// Type T needs to have fields value and lazy.
// L must be the type of T.lazy.
// Type W from apply will be either T.lazy or U.
// Define operator = between all 4 of these pairs of types:
// {T.value, T.lazy} x {U, T.lazy}.
template<typename T, typename U, typename L>
class RangeReplace : public LazyRangeUpdate<T, U, L> {
  public:
	RangeReplace(int left, int right, const U& upd) 
	: LazyRangeUpdate<T, U, L>(left, right, upd) {}

	virtual void apply(TravelState& s, U& updater) {
		(*this->segTree).v[s.now()].value = updater;
		(*this->segTree).v[s.now()].lazy = updater;
	}

	virtual void apply(TravelState& s, L& updater) {
		(*this->segTree).v[s.now()].value = updater;
		(*this->segTree).v[s.now()].lazy = updater;
	}
};

// Same as RangeReplace, but with operator += instead of =.
template<typename T, typename U, typename L>
class RangeAdd : public LazyRangeUpdate<T, U, L> {
  public:
	RangeAdd(int left, int right, const U& upd) : 
	LazyRangeUpdate<T, U, L>(left, right, upd) {}

	virtual void apply(TravelState& s, U& updater) {
		(*this->segTree).v[s.now()].value += updater;
		(*this->segTree).v[s.now()].lazy += updater;
	}

	virtual void apply(TravelState& s, L& updater) {
		(*this->segTree).v[s.now()].value += updater;
		(*this->segTree).v[s.now()].lazy += updater;
	}
};

template<typename T>
class InitFromVector : public Build<T> {
	std::vector<T>& v;
  public:
  	InitFromVector(std::vector<T>& v) : v(v) {}

  	virtual void stopping(TravelState& s) {
  		(*this->segTree).v[s.now()] = v[s.left-1];
  	}
};

template<typename T>
class SegmentTree {
  public:
	int size;
	std::vector<T> v;

	SegmentTree(int size) : size(size) {
		v.resize(4*size);
	}
	
	virtual void recalculate(T& node, const T& leftSon, const T& rightSon)=0;

	void travel(TravelState& s, BaseOp<T>& op) {
		if (op.shouldStop(s)) {
			op.stopping(s);
		} else {
			op.going(s);
			if (op.shouldGoLeft(s)) {
				auto sl = s.goLeft();
				travel(sl, op);
			}
			if (op.shouldGoRight(s)) {
				auto sr = s.goRight();
				travel(sr, op);
			}
			op.returning(s);
		}
	}

	void apply(BaseOp<T>& op) {
		op.bind(this);
		op.before();
		auto state = TravelState(1, 1, size);
		travel(state, op);
		op.after();
		op.unbind();
	}
};

template<typename T>
class SumSegmentTree : public SegmentTree<T> {
  public:
  	SumSegmentTree(int size) : SegmentTree<T>(size) {}
	virtual void recalculate(T& node, const T& leftSon, const T& rightSon) {
		node = leftSon + rightSon;
	}
};

template<typename T>
class MaxSegmentTree : public SegmentTree<T> {
  public:
  	MaxSegmentTree(int size) : SegmentTree<T>(size) {}
  	virtual void recalculate(T& node, const T& leftSon, const T& rightSon) {
  		if (leftSon > rightSon)
  			node = leftSon;
  		else node = rightSon;
	}
};

}

using namespace std;
using namespace segment_tree;

int main() {
	freopen("arbint.in", "r", stdin);
	freopen("arbint.out", "w", stdout);
	int n, m;

	cin >> n >> m;

	vector<int> v(n);
	for (int i = 0; i < n; ++i) {
		cin >> v[i];
	}

	MaxSegmentTree<int> tree(n);

	auto op = InitFromVector<int>(v);
	tree.apply(op);
	
	for (int i = 1; i <= m; ++i) {
		int t, a, b;
		cin >> t >> a >> b;
		if (t == 0) {
			auto op = MaxRangeQuery<int>(a, b, 0);
			tree.apply(op);
			cout << op.result << "\n";
		} else {
			auto op = PointReplace<int, int>(a, b);
			tree.apply(op);
		}
	}
}