4n действительно грубовато но и 2n мало.
тут надо 2 * (min k такое что 2^k >= n)
например для стандартного N <= 100000 хватит
int t[1 << 18]
А вообще пора http://e-maxx.ru/algo/segment_tree переписывать Когда дерево выровнено по 2^k все намного удобнее - можно легко определить за какой сегмент t[ i ] отвечает, легче делать Update и Build - без рекурсии.
Вот мой шаблон:
template <class T>
struct SegmentTree
{
SegmentTree(const T* begin, const T* end)
{
int sz = end - begin;
Create(sz);
copy(begin, end, values + dx);
for (int i = dx - 1; i >= 1; i--)
{
values[i] = values[i * 2] + values[i * 2 + 1];
}
}
SegmentTree(int sz)
{
Create(sz);
}
void Create(int sz)
{
dx = 1;
while (dx < sz)
dx *= 2;
values = new T[dx * 2];
memset(values, 0, sizeof(T) * dx * 2);
}
~SegmentTree()
{
delete[] values;
}
void Update(int pos, T value)
{
pos += dx;
values[pos] = value;
while (pos > 1)
{
pos /= 2;
values[pos] = values[pos * 2] + values[pos * 2 + 1];
}
}
T GetSegment(int l, int r, int pos, int tl, int tr)
{
if (l == tl && r == tr)
return values[pos];
int m = (tl + tr) / 2;
if (r <= m)
return GetSegment (l, r, pos * 2, tl, m);
if (l >= m)
return GetSegment (l, r, pos * 2 + 1, m, tr);
return GetSegment (l, m, pos * 2, tl, m) + GetSegment (m, r, pos * 2 + 1, m, tr);
}
T GetSegment(int l, int r)
{
return GetSegment(l, r, 1, 0, dx);
}
T* values;
int dx;
};
int a[] = {1,2,3,4};
SegmentTree<int> tree(a, a + 4);
int res = tree.GetSegment(0, 4); // r - как и в stl указывает на следующий за последним.