提出 #53459424


ソースコード 拡げる

Copy
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
/* XY */
#define BIT_MAX 212345
int bit_table[BIT_MAX];
void bit_add(int pos, int value) {
pos++;
while (pos <= BIT_MAX) {
bit_table[pos - 1] += value;
pos += pos & (-pos);
}
}
int bit_sum(int pos) {
int sum = 0;
pos++;
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

/* !!!縦のことをX、横のことをYと書いて誤読を誘う引っ掛け問題!!! */

#define BIT_MAX 212345

int bit_table[BIT_MAX];

void bit_add(int pos, int value) {
	pos++;
	while (pos <= BIT_MAX) {
		bit_table[pos - 1] += value;
		pos += pos & (-pos);
	}
}

int bit_sum(int pos) {
	int sum = 0;
	pos++;
	while (pos > 0) {
		sum += bit_table[pos - 1];
		pos -= pos & (-pos);
	}
	return sum;
}

char syougaibutu[212345];

struct xy_s {
	int X, Y;
};

int cmp(const void* x, const void* y) {
	struct xy_s a = *(const struct xy_s*)x, b = *(const struct xy_s*)y;
	if (a.Y != b.Y) return a.Y < b.Y ? -1 : 1;
	return a.X < b.X ? -1 : a.X > b.X;
}

int H, W, M;
struct xy_s XY[212345];

int main(void) {
	int i;
	int64_t ans;
	int uekara_ikenai_mode = 0;
	int next_sgb = 0;
	if (scanf("%d%d%d", &H, &W, &M) != 3) return 1;
	for (i = 0; i < M; i++) {
		if (scanf("%d%d", &XY[i].X, &XY[i].Y) != 2) return 1;
	}
	qsort(XY, M, sizeof(*XY), cmp);
	ans = (int64_t)H * W;
	if (XY[0].Y == 1) {
		/* 最初の列に障害物 → その下全部に障害物があるとみなす */
		/* 障害物本体は、後で処理するからここでは処理しない */
		/* 障害物があるとしておけば後で引かれるから、ここでは引かない */
		for (i = XY[0].X + 1; i <= H; i++) {
			bit_add(i, 1);
			syougaibutu[i] = 1;
		}
	}
	for (i = 1; i <= W; i++) {
		if (uekara_ikenai_mode) {
			/* 上から行けないとき、左に障害物があれば行けない */
			ans -= bit_sum(H);
		}
		for (;next_sgb < M && XY[next_sgb].Y == i; next_sgb++) {
			if (XY[next_sgb].X == 1) {
				if (!uekara_ikenai_mode) ans -= bit_sum(H);
				uekara_ikenai_mode = 1;
			}
			if (!uekara_ikenai_mode && (next_sgb == 0 || XY[next_sgb].Y != XY[next_sgb - 1].Y)) {
				/* その列で最初の障害物の所には上から行けるから、カウントする */
				ans--;
				if (!syougaibutu[XY[next_sgb].X]) {
					bit_add(XY[next_sgb].X, 1);
					syougaibutu[XY[next_sgb].X] = 1;
				}
				/* 行けない場所をカウントする */
				ans -= bit_sum(H) - bit_sum(XY[next_sgb].X);
			} else {
				if (!syougaibutu[XY[next_sgb].X]) {
					/* 障害物が無ければ行けるなら、カウントする */
					ans--;
					bit_add(XY[next_sgb].X, 1);
					syougaibutu[XY[next_sgb].X] = 1;
				}
			}
		}
	}
	printf("%" PRId64 "\n", ans);
	return 0;
}

/*

右に行く → 下に行く
or
下に行く → 右に行く

(戻っても無駄)

上からも左からも行けない → 行けない

障害物をYの昇順にソート
同点 → Xの昇順にソート (Y=1 のとき、一番上の障害物を最初に持ってくるため)

注目している障害物より左の障害物の配置をセグメント木で記録
障害物があった → その下で、左に障害物がある位置には行けない

※同じYに複数障害物がある場合に注意
障害物がある → 行けない
二重カウント注意

X=1 に障害物があったら、打ち切り (1手目の移動が止まるので)
Y=1 の障害物は、一番上のやつを行ける範囲として使う

セグメント木ではなく、BITでおk

-----

X=1 に障害物があったら、打ち切り (1手目の移動が止まるので) ← 嘘

.#....
......

だったら、下 → 右 で2行目全部行ける

2 6 1
2 1

→ 7

「打ち切り」にはせず、「上から行けないモード」で続行
同様に、1列目に障害物がある場合も、そこで止めず、その下全部に障害物があるとして扱う

-----

「上から行けないモード」のとき、左から行けない場所には行けない

.#....
...#..
......

3 6 2
2 1
4 2

→ 10

↑誤読があったので上の自作ケースは誤り
正しくはそれぞれ

2 6 1
1 2

3 6 2
1 2
2 4

-----

.#
#.

2 2 2
1 2
2 1

→ 1

..
#.
#.

3 2 2
2 1
3 1

→ 4

..
##
..

3 2 2
2 1
2 2

→ 2

-----

最初に「上から行けないモード」にしたとき、既存の障害物分を引けてなかった
書かれているテストケースで誤答出てるのになんで見逃してるんだよバカ

*/

提出情報

提出日時
問題 F - Rook on Grid
ユーザ mikecat
言語 C (gcc 12.2.0)
得点 600
コード長 4387 Byte
結果 AC
実行時間 59 ms
メモリ 4756 KB

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 600 / 600
結果
AC × 3
AC × 29
セット名 テストケース
Sample sample_01.txt, sample_02.txt, sample_03.txt
All hand_01.txt, hand_02.txt, hand_03.txt, hand_04.txt, hand_05.txt, hand_06.txt, random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, random_13.txt, random_14.txt, random_15.txt, random_16.txt, random_17.txt, random_18.txt, random_19.txt, random_20.txt, sample_01.txt, sample_02.txt, sample_03.txt
ケース名 結果 実行時間 メモリ
hand_01.txt AC 1 ms 1632 KB
hand_02.txt AC 1 ms 1656 KB
hand_03.txt AC 1 ms 1672 KB
hand_04.txt AC 3 ms 2732 KB
hand_05.txt AC 0 ms 1680 KB
hand_06.txt AC 1 ms 1640 KB
random_01.txt AC 59 ms 4704 KB
random_02.txt AC 57 ms 4736 KB
random_03.txt AC 59 ms 4712 KB
random_04.txt AC 59 ms 4672 KB
random_05.txt AC 58 ms 4756 KB
random_06.txt AC 58 ms 4684 KB
random_07.txt AC 58 ms 4548 KB
random_08.txt AC 1 ms 2628 KB
random_09.txt AC 1 ms 2700 KB
random_10.txt AC 1 ms 2600 KB
random_11.txt AC 46 ms 4748 KB
random_12.txt AC 45 ms 4556 KB
random_13.txt AC 45 ms 4696 KB
random_14.txt AC 45 ms 4688 KB
random_15.txt AC 45 ms 4604 KB
random_16.txt AC 45 ms 4604 KB
random_17.txt AC 45 ms 4748 KB
random_18.txt AC 1 ms 1780 KB
random_19.txt AC 1 ms 1828 KB
random_20.txt AC 1 ms 1684 KB
sample_01.txt AC 0 ms 1752 KB
sample_02.txt AC 0 ms 1756 KB
sample_03.txt AC 1 ms 1640 KB


2024-05-14 (火)
05:31:52 +09:00