Apparently screwed up with classes. Help me to understand.
import java.util.*; import java.lang.*; import java.io.*; class node { int ones, twos, add; } class tree { //int[] st = new int[1 << 18]; node[] st = new node[1<<18]; //В вершину VSun сверху производится проталкивание значения add (0 ≤ add ≤ 2). Вершина VSun //является левым сыном, если SunType = 'L' и правым если SunType = 'R'. Отцу вершины VSun //соответствует отрезок [LeftPos, RightPos], Middle = (LeftPos + RightPos) / 2. Будем add //раз производить в вершине VSun циклический сдвиг количества нулей, единиц и двоек. Каждый //циклический сдвиг соответствует проталкиванию единицы из отца в VSun. public void MakeShift(int VSun, int add, char SunType, int LeftPos, int Middle, int RightPos) { st[VSun].add = (st[VSun].add + add) % 3; while (add>0) { //Количество двоек становится равным числу единиц. Количество единиц становится равным числу нулей. int _Ones = st[VSun].ones; //Количество единиц становится равным числу нулей. Проталкивание происходит в левом сыне, если //SunType = 'L'. Если VSun является левым сыном, то длина соответствующего ему отрезка равна //Middle – LeftPos + 1. Если правым сыном, то RightPos – Middle. if (SunType=='L') st[VSun].ones = Middle - LeftPos + 1 - st[VSun].ones - st[VSun].twos; else st[VSun].ones = RightPos - Middle - st[VSun].ones - st[VSun].twos; //Количество двоек становится равным числу единиц. st[VSun].twos = _Ones; } } //Если значение add в вершине v отлично от нуля, то следует его протолкнуть на один уровень //вниз. После проталкивания add в вершине v ставим равным нулю. Значение add в сыновьях v //увеличиваем на протолкнутое значение. Пересчитываем значения ones и twos в сыновьях. void Push(int v, int LeftPos, int Middle, int RightPos) { MakeShift(2 * v, st[v].add, 'L', LeftPos, Middle, RightPos); MakeShift(2 * v + 1, st[v].add, 'R', LeftPos, Middle, RightPos); st[v].add = 0; } //Вершине v соответствует отрезок [LeftPos; RightPos ]. Функция IncValue //прибавляет ко всем элементам отрезка[Left; Right] значение 1. public void IncValue(int v, int LeftPos, int RightPos, int Left, int Right) { if (Left > Right) return; if (LeftPos == Left && RightPos == Right) { st[v].add = (st[v].add + 1) % 3; int _Ones = st[v].ones; st[v].ones = Right - Left + 1 - st[v].ones - st[v].twos; st[v].twos = _Ones; return; } int Middle = (LeftPos + RightPos) / 2; //Проведем проталкивание, если add не равно нулю. Push(v, LeftPos, Middle, RightPos); //Рекурсивно обрабатываем левого и правого сына текущей вершины дерева отрезков. IncValue(2 * v, LeftPos, Middle, Left, Math.min(Middle, Right)); IncValue(2 * v + 1, Middle + 1, RightPos, Math.max(Left, Middle + 1), Right); //Пересчитываем количество единиц и двоек на отрезке, соответствующему вершине v, через соответствующие значения детей. st[v].ones = st[2 * v].ones + st[2 * v + 1].ones; st[v].twos = st[2 * v].twos + st[2 * v + 1].twos; } //Вершине v соответствует отрезок [LeftPos; RightPos]. Функция Query возвращает количество нулей на отрезке [Left; Right]. int Query(int v, int LeftPos, int RightPos, int Left, int Right) { if (Left > Right) return 0; //Количество нулей на отрезке равно длине отрезка минус количество единиц и двоек на нем. if (LeftPos == Left && RightPos == Right) return (RightPos - LeftPos + 1) - st[v].ones - st[v].twos; int Middle = (LeftPos + RightPos) / 2; Push(v, LeftPos, Middle, RightPos); return Query(2 * v, LeftPos, Middle, Left, Math.min(Middle, Right)) + Query(2 * v + 1, Middle + 1, RightPos, Math.max(Left, Middle + 1), Right); } } public class Main { public static void main (String[] args) throws java.lang.Exception { Scanner in = new Scanner(System.in); tree x = new tree(); int n = in.nextInt(); int m = in.nextInt(); for (int i=0; i < m; i++) { int type = in.nextInt(); int L = in.nextInt(); int R = in.nextInt(); if(type==1) { System.out.println(x.Query(1, 0, n - 1, L, R)); } else { x.IncValue(1, 0, n - 1, L, R); } } } }