クエリメニュー【′I′の数・ドーナツ・点の幅】
【STEP: 1】コード
reader.on('close', () => {
const [N, K] = lines[0].split(' ').map(Number);
const A = [0]; // A は 累積和を保存するための配列
const P = N / 3;
for (let i = 1; i <= N; i++) {
A.push(A[i - 1] + Number(lines[i])); // A に "I" の数の累積和を保存
}
for (let i = N + 1; i <= N + K; i++) {
let [a, b] = [0, 0]; // [a, b] は A と B の点数
const [Al, Ar, Bl, Br] = lines[i].split(' ').map(Number);
if (Ar - Al + 1 >= P && Br - Bl + 1 >= P) { // 2人共反則なので…
console.log('DRAW'); // "DRAW"(引き分け)
} else if (Ar - Al + 1 >= P) { // A が反則なので…
console.log('B'); // B の勝ち
} else if (Br - Bl + 1 >= P) { // B が反則なので…
console.log('A'); // A の勝ち
} else {
a = A[Ar] - A[Al - 1]; // A の得点
b = A[Br] - A[Bl - 1]; // B の得点
if (a === b) { // 得点が同じなら…
console.log('DRAW'); // "DRAW"(引き分け)
} else {
console.log(a > b ? 'A' : 'B'); // a > b なら "A" を出力 さもなくば "B" を出力
}
}
}
});
累積和 を使って 区間和を求めています。
【STEP: 2】コード
reader.on('close', () => {
const [H, W, N] = lines[0].split(' ').map(Number);
const D = []; // チョコの数(入力値)を保存するための 2 次元配列
const S = [new Array(W + 1).fill(0)]; // チョコの数の 2 次元累積和
for (let h = 1; h <= H; h++) {
D.push(lines[h].split(' ').map(Number)); // D に入力値の配列を保存
S.push([0]); // S に [0] を保存
for (let w = 1; w <= W; w++) {
// D の累積和を計算して S に保存
S[h][w] = (S[h - 1][w] + S[h][w - 1] + D[h - 1][w - 1] - S[h - 1][w - 1]);
}
}
for (let n = H + 1; n <= N + H; n++) {
const [y, x, b, s] = lines[n].split(' ').map(Number);
const [bs, ss] = [b, s].map(x => (x - 1) / 2);
const [sy, sx, ey, ex, ssy, ssx, sey, sex] = [y - bs, x - bs, y + bs, x + bs, y - ss, x - ss, y + ss, x + ss];
const Br = S[ey][ex] - S[sy - 1][ex] - S[ey][sx - 1] + S[sy - 1][sx - 1];
const Sr = S[sey][sex] - S[ssy - 1][sex] - S[sey][ssx - 1] + S[ssy - 1][ssx - 1];
console.log(Br - Sr);
}
});
二次元累積和 の配列を生成し 範囲内の 値を 取得しました。
【FINAL】コード
reader.on('close', () => {
const [N, K] = lines[0].split(' ').map(Number);
const Ns = Math.sqrt(N);
const S = [];
const Min = [];
const Max = [];
for (let i = 1; i <= N; i++) {
S.push(Number(lines[i]));
}
const A = [...S];
for (let i = 0; i < Ns; i++) {
const s = S.splice(0, Ns);
let [max, min] = [s[0], s[0]];
S.push(s);
for (let i = 1; i < Ns; i++) {
max = Math.max(max, s[i]);
min = Math.min(min, s[i]);
}
Max.push(max);
Min.push(min);
}
for (let k = N + 1; k <= N + K; k++) {
const [Al, Ar, Bl, Br] = lines[k].split(' ').map(x => x - 1);
let A_point = Al;
let [Amin, Amax] = [A[Al], A[Al]];
while (A_point <= Ar) {
if (A_point % Ns === 0 && A_point + Ns - 1 <= Ar) {
Amin = Math.min(Amin, Min[A_point / Ns]);
Amax = Math.max(Amax, Max[A_point / Ns]);
A_point += Ns;
} else {
Amin = Math.min(Amin, A[A_point]);
Amax = Math.max(Amax, A[A_point]);
A_point++;
}
}
let B_pointt = Bl;
let [Bmin, Bmax] = [A[Bl], A[Bl]];
while (B_pointt <= Br) {
if ((B_pointt) % Ns === 0 && B_pointt + Ns - 1 <= Br) {
Bmin = Math.min(Bmin, Min[B_pointt / Ns]);
Bmax = Math.max(Bmax, Max[B_pointt / Ns]);
B_pointt += Ns;
} else {
Bmin = Math.min(Bmin, A[B_pointt]);
Bmax = Math.max(Bmax, A[B_pointt]);
B_pointt++;
}
}
const Bp = Bmax - Bmin;
const Ap = Amax - Amin;
if (Ap > Bp) {
console.log('A');
} else if (Ap < Bp) {
console.log('B');
} else {
console.log('DRAW');
}
}
});
一応 これでクリアできましたけど もう少し コードを整理しないと駄目ですね。 (๑ ᷄ω ᷅)
コメント