#include <cstdio>
#include <cassert>
struct Nod {
long long suma;
long long dimensiune;
long long adaugare;
Nod* fiuSt;
Nod* fiuDr;
};
template <class Type, int size>
class Prealloc {
private:
Type data[size];
Type* addresses[size];
int available;
public:
Prealloc() {
this->available = size;
int i;
for (i = 0; i < size; ++i) {
this->addresses[i] = &this->data[i];
}
}
Type* newType() {
--this->available;
return this->addresses[this->available];
}
void deleteType(Type* address) {
this->addresses[this->available] = address;
++this->available;
}
};
Prealloc<Nod, 2800000> alloc;
Nod* arboreGol = nullptr;
Nod* creeazaNod(long long adaugare, Nod* fiuSt, Nod* fiuDr) {
Nod* answer = alloc.newType();
if (fiuSt == arboreGol)
*answer = Nod {
adaugare,
1,
adaugare,
fiuSt,
fiuDr};
else
*answer = Nod {
fiuSt->suma + fiuDr->suma + adaugare * (fiuSt->dimensiune + fiuDr->dimensiune),
fiuSt->dimensiune + fiuDr->dimensiune,
adaugare,
fiuSt,
fiuDr};
return answer;
}
Nod* construieste(int* inceput, int* sfarsit) {
int N = sfarsit - inceput;
if (N == 1)
return creeazaNod(*inceput, arboreGol, arboreGol);
return creeazaNod(0,
construieste(inceput, inceput + (N / 2)),
construieste(inceput + (N / 2), sfarsit));
}
// query(de la 0 la 2 inclusiv)
// adica i = 0, j = 3
// dimensiune = 6
// 0 1 2 3 4 5
// query(de la 3 la 5 inclusiv)
// adica i = 3, j = 6
Nod* actualizare(Nod* arbore, int L, int R, int V) {
// interval = [0, arebore->dimensiune)
assert(0 <= L && L < R && R <= arbore->dimensiune);
if (L == 0 && R == arbore->dimensiune)
return creeazaNod(
arbore->adaugare + V,
arbore->fiuSt,
arbore->fiuDr);
else if (R <= arbore->fiuSt->dimensiune)
return creeazaNod(
arbore->adaugare,
actualizare(
arbore->fiuSt,
L,
R,
V),
arbore->fiuDr);
else if (arbore->fiuSt->dimensiune <= L)
return creeazaNod(
arbore->adaugare,
arbore->fiuSt,
actualizare(
arbore->fiuDr,
L - arbore->fiuSt->dimensiune,
R - arbore->fiuSt->dimensiune,
V));
else
return creeazaNod(
arbore->adaugare,
actualizare(
arbore->fiuSt,
L,
arbore->fiuSt->dimensiune,
V),
actualizare(
arbore->fiuDr,
0,
R - arbore->fiuSt->dimensiune,
V));
}
long long interogare(Nod* arbore, int i, int j) {
// interval = [0, arebore->dimensiune)
assert(0 <= i && i < j && j <= arbore->dimensiune);
if (i == 0 && j == arbore->dimensiune)
return arbore->suma;
else if (j <= arbore->fiuSt->dimensiune)
return arbore->adaugare * (j - i) +
interogare(arbore->fiuSt, i, j);
else if (arbore->fiuSt->dimensiune <= i)
return arbore->adaugare * (j - i) +
interogare(arbore->fiuDr,
i - arbore->fiuSt->dimensiune,
j - arbore->fiuSt->dimensiune);
else
return arbore->adaugare * (j - i) +
interogare(arbore->fiuSt,
i,
arbore->fiuSt->dimensiune) +
interogare(arbore->fiuDr,
0,
j - arbore->fiuSt->dimensiune);
}
int main(void) {
freopen("ants.in", "r", stdin);
freopen("ants.out", "w", stdout);
int N, M;
scanf("%d%d", &N, &M);
int *A = new int[M];
for (int i = 0; i < M; ++i) {
scanf("%d", &A[i]);
}
long long S = 0;
Nod** orase = new Nod*[1 + N];
orase[1] = construieste(A, A + M);
for (int ver = 2; ver <= N; ver++) {
int P, X, Y, V, Z, T;
scanf("%d%d%d%d%d%d", &P, &X, &Y, &V, &Z, &T);
int L = (X + S) % M;
int R = (Y + S) % M;
int i = (Z + S) % M;
int j = (T + S) % M;
orase[ver] = actualizare(orase[P], L, R + 1, V);
S = interogare(orase[ver], i, j + 1);
printf("%lld\n", S);
}
return 0;
}