Problem:
城壁 (Rampart)
歴史学者である JOI 教授は，かつて存在した IOI 王国について研究している．
過去の調査によると，IOI 王国は縦
H
行，横
W
列のマスに区切られた長方形の形をしていた．IOI 王国の首都は，防衛のために城壁で囲われていた．
IOI 王国の首都を囲う城壁は次のような形をしている．城壁には大きさと呼ばれる値が定まっている．大きさ
s
(
s
≥ 3) の城壁とは，
s
×
s
の正方形の領域から外周以外の (
s
− 2) × (
s
− 2) の正方形の領域を除いたものである．
調査によると，首都を囲う城壁の大きさは
L
以上であった．また，IOI 王国のいくつかのマスには城壁が存在しなかったことがわかっている．
JOI 教授は，さらなる研究のために，城壁としてありうるものが何通りあるかを知りたい．
課題
IOI 王国の大きさと，城壁の大きさの最小値，城壁が存在しなかったことが分かっているマスの情報が与えられたとき，城壁としてありうるものは何通りあるかを求めるプログラムを作成せよ．
入力
標準入力から以下のデータを読み込め．
1 行目には，整数
H
,
W
,
L
,
P
が空白を区切りとして書かれている．これは，IOI 王国は縦
H
行，横
W
列のマスに区切られた長方形の形をしており，城壁の大きさは
L
以上であり，城壁が存在しなかったことがわかっているマスが
P
マス存在することを表す．
続く
P
行のうちの
i
行目 (1 ≤
i
≤
P
) には，整数
A
i
,
B
i
が空白を区切りとして書かれている．これは，IOI 王国の上から
A
i
行目，左から
B
i
列目のマスには城壁が存在しなかったことがわかっていることを表す．
出力
標準出力に，城壁としてありうるものは何通りあるかを表す整数を 1 行で出力せよ.
制限
すべての入力データは以下の条件を満たす．
1 ≤
H
≤ 4 000．
1 ≤
W
≤ 4 000．
3 ≤
L
≤
H
かつ 3 ≤
L
≤
W
．
0 ≤
P
≤ 100 000．
1 ≤
A
i
≤
H
(1 ≤
i
≤
P
)．
1 ≤
B
i
≤
W
(1 ≤
i
≤
P
)．
(
A
i
,
B
i
) ≠ (
A
j
,
B
j
) (1 ≤
i
<
j
≤
P
)．
入出力例
入力例 1
5 5 3 2
2 2
4 3
出力例 1
4
この入力例の場合，城壁としてありうるものは以下の 4 通りが考えられる．ただし，× で示したマスは城壁が存在しなかったことがわかっているマスである．
入力例 2
7 8 4 3
2 2
3 7
6 5
出力例 2
13
入力例 3
4000 4000 1234 4
1161 3028
596 1892
3731 2606
702 1530
出力例 3
7050792912
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 4001

enum Type {
    LEFT_UP,
    RIGHT_UNDER,
};

struct Info {
    Info(Type arg_type, short arg_max_len, short arg_loc) {
        type = arg_type;
        max_len = arg_max_len;
        loc = arg_loc; // 斜めのラインにおける相対位置
    }
    bool operator<(const struct Info &arg) const {
        if (max_len != arg.max_len) {
            return max_len > arg.max_len; // 最大長の降順
        } else {
            return type < arg.type; // 長さが同じなら、LEFT_UPを左に持ってくる
        }
    }
    Type type;
    short max_len, loc;
};

int H, W, min_len, P;
int BIT_MAX;
short LIMIT[2][NUM][NUM];
int BIT[2][NUM];
bool table[NUM][NUM];
short dp[NUM][NUM];

void add(Type type, int loc, int value) {
    BIT[type][loc] += value;
    loc += loc & -loc; // 最後の1ビットを足した場所が次の更新場所

    while (loc <= BIT_MAX) {
        BIT[type][loc] += value;
        loc += loc & -loc;
    }
}

int getSum(Type type, int loc) {
    int sum = BIT[type][loc];
    loc -= loc & -loc; // 最後の1ビットを引いた場所が次の加算場所

    while (loc > 0) {
        sum += BIT[type][loc];
        loc -= loc & -loc;
    }
    return sum;
}

int calc(Type type, int left, int right) { // left～rightの区間の総和を求める
    return getSum(type, right) - getSum(type, left - 1);
}

void init_LIMIT(Type type) {
    for (int row = 0; row < H; row++) {
        for (int col = 0; col < W; col++) {
            LIMIT[type][row][col] = NUM;
        }
    }
}

void update_LIMIT(Type type) {
    for (int row = 0; row < H; row++) {
        for (int col = 0; col < W; col++) {
            LIMIT[type][row][col] = min(LIMIT[type][row][col], dp[row][col]);
        }
    }
}

bool rangeCheck(int row, int col) {
    return row >= 0 && row <= H - 1 && col >= 0 && col <= W - 1;
}

int main() {
    scanf("%d %d %d %d", &H, &W, &min_len, &P);

    for (int row = 0; row < H; row++) {
        for (int col = 0; col < W; col++) {
            table[row][col] = true;
        }
    }

    int tmp_row, tmp_col;

    for (int loop = 0; loop < P; loop++) {
        scanf("%d %d", &tmp_row, &tmp_col);
        tmp_row--;
        tmp_col--;
        table[tmp_row][tmp_col] = false;
    }

    // 各場所からの最大長を計算する

    // 左上基準
    init_LIMIT(LEFT_UP);

    // 右方向への最大長さ
    for (int row = 0; row < H; row++) {
        dp[row][W - 1] = table[row][W - 1] ? 1 : 0;
    }

    for (int col = W - 2; col >= 0; col--) {
        for (int row = 0; row < H; row++) {
            dp[row][col] = table[row][col] ? dp[row][col + 1] + 1 : 0;
        }
    }
    update_LIMIT(LEFT_UP);

    // 下方向への最大長さ
    for (int col = 0; col < W; col++) {
        dp[H - 1][col] = table[H - 1][col] ? 1 : 0;
    }

    for (int row = H - 2; row >= 0; row--) {
        for (int col = 0; col < W; col++) {
            dp[row][col] = table[row][col] ? dp[row + 1][col] + 1 : 0;
        }
    }
    update_LIMIT(LEFT_UP);

    // 右下基準
    init_LIMIT(RIGHT_UNDER);

    // 左方向への最大長さ
    for (int row = 0; row < H; row++) {
        dp[row][0] = table[row][0] ? 1 : 0;
    }

    for (int col = 1; col < W; col++) {
        for (int row = 0; row < H; row++) {
            dp[row][col] = table[row][col] ? dp[row][col - 1] + 1 : 0;
        }
    }
    update_LIMIT(RIGHT_UNDER);

    // 上方向への最大長さ
    for (int col = 0; col < W; col++) {
        dp[0][col] = table[0][col] ? 1 : 0;
    }

    for (int row = 1; row < H; row++) {
        for (int col = 0; col < W; col++) {
            dp[row][col] = table[row][col] ? dp[row - 1][col] + 1 : 0;
        }
    }
    update_LIMIT(RIGHT_UNDER);

    vector<Info> V;
    ll ans = 0;

    // 斜めのラインごとに計上処理を行う
    int start_row = 0, start_col = W - 2;
    int left, right;

    while (true) {
        V.clear();
        BIT_MAX = 0;

        tmp_row = start_row, tmp_col = start_col;
        // 斜めのラインのデータを走査する
        while (rangeCheck(tmp_row, tmp_col)) {
            V.emplace_back(LEFT_UP, LIMIT[LEFT_UP][tmp_row][tmp_col], BIT_MAX + 1);
            V.emplace_back(RIGHT_UNDER, LIMIT[RIGHT_UNDER][tmp_row][tmp_col], BIT_MAX + 1);

            tmp_row++;
            tmp_col++;
            BIT_MAX++;
        }

        sort(V.begin(), V.end());

        // BIT木の初期化
        for (int i = 0; i <= BIT_MAX; i++) {
            BIT[LEFT_UP][i] = 0;
            BIT[RIGHT_UNDER][i] = 0;
        }

        // 最大長が大きい方から、降順に処理する
        for (const auto &info : V) {
            if (info.type == LEFT_UP) {
                left = info.loc + min_len - 1;
                right = info.loc + info.max_len - 1;

                if (left <= right) {
                    ans += calc(RIGHT_UNDER, left, right); // ペアになるものを探す
                }
            } else {
                right = info.loc - min_len + 1;
                left = info.loc - info.max_len + 1;

                if (left <= right) {
                    ans += calc(LEFT_UP, left, right);
                }
            }

            add(info.type, info.loc, 1);
        }

        if (start_row == H - 2 && start_col == 0) {
            break;
        }

        if (start_row == 0) {
            if (start_col != 0) {
                start_col--;
            } else {
                start_row++;
            }
        } else {
            start_row++;
        }
    }

    printf("%lld\n", ans);

    return 0;
}
accuracy: 1
time_ms: 2450
memory_kb: 113156
final_rank: 10

code_snippet: #include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool px[4096][4096], py[4096][4096]; short sa[4096][4096], sb[4096][4096], sc[4096][4096], sd[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096], rui[128]; uint64_t seq[128];
int calc(int N) {
	memset(cnt, 0, sizeof(cnt));
	memset(rui, 0, sizeof(rui));
	memset(seq, 0, sizeof(seq));
	for (int i = 0; i < N; ++i) ++cnt[sy[i] + i + 2];
	for (int i = 0; i <= N; ++i) cnt[i + 2] += cnt[i + 1];
	for (int i = 0; i < N; ++i) ord[cnt[sy[i] + i + 1]++] = i;
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			++rui[ord[j] >> 6];
			seq[ord[j] >> 6] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		for (int j = liml; j < limr; ++j) ans += rui[j];
		ans -= __builtin_popcountll(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += __builtin_popcountll(seq[limr] & ((1ULL << (pr & 63)) - 1));
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		px[x][y] = true;
		py[y][x] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (px[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (py[i][j]) last = j;
			sc[i][j] = j - last;
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (px[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (py[i][j]) last = j;
			sd[i][j] = last - j;
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = min(sa[j][i + j], sc[i + j][j]);
			sy[j - d] = min(sb[j][i + j], sd[i + j][j]);
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 900
memory_kb: 158864
final_rank: 7

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool placex[4096][4096], placey[4096][4096]; short sa[4096][4096], sb[4096][4096], sc[4096][4096], sd[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096];
short rui[128]; uint64_t seq[128];
int calc(int N) {
	fill(cnt, cnt + N + 3, 0);
	for (int i = 0; i < N; ++i) {
		++cnt[sy[i] + i + 2];
	}
	for (int i = 0; i <= N; ++i) {
		cnt[i + 2] += cnt[i + 1];
	}
	for (int i = 0; i < N; ++i) {
		ord[cnt[sy[i] + i + 1]++] = i;
	}
	fill(rui, rui + (N >> 6) + 1, 0);
	fill(seq, seq + (N >> 6) + 1, 0);
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			++rui[ord[j] >> 6];
			seq[ord[j] >> 6] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		for (int j = liml; j < limr; ++j) {
			ans += rui[j];
		}
		ans -= __builtin_popcountll(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += __builtin_popcountll(seq[limr] & ((1ULL << (pr & 63)) - 1));
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		placex[x][y] = true;
		placey[y][x] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (placex[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (placey[i][j]) last = j;
			sc[i][j] = j - last;
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (placex[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (placey[i][j]) last = j;
			sd[i][j] = last - j;
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = min(sa[j][i + j], sc[i + j][j]);
			sy[j - d] = min(sb[j][i + j], sd[i + j][j]);
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 910
memory_kb: 158868
final_rank: 8

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool placex[4096][4096], placey[4096][4096]; short sa[4096][4096], sb[4096][4096], sc[4096][4096], sd[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096];
short rui[128]; uint64_t seq[128];
int popcnt(uint64_t x) {
	int ans = 0;
	while (x) {
		ans += (x & 1);
		x >>= 1;
	}
	return ans;
}
int calc(int N) {
	fill(cnt, cnt + N + 3, 0);
	for (int i = 0; i < N; ++i) {
		++cnt[sy[i] + i + 2];
	}
	for (int i = 0; i <= N; ++i) {
		cnt[i + 2] += cnt[i + 1];
	}
	for (int i = 0; i < N; ++i) {
		ord[cnt[sy[i] + i + 1]++] = i;
	}
	fill(rui, rui + (N >> 6) + 1, 0);
	fill(seq, seq + (N >> 6) + 1, 0);
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			++rui[ord[j] >> 6];
			seq[ord[j] >> 6] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		for (int j = liml; j < limr; ++j) {
			ans += rui[j];
		}
		ans -= __builtin_popcountll(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += __builtin_popcountll(seq[limr] & ((1ULL << (pr & 63)) - 1));
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		placex[x][y] = true;
		placey[y][x] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (placex[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (placey[i][j]) last = j;
			sc[i][j] = j - last;
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (placex[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (placey[i][j]) last = j;
			sd[i][j] = last - j;
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = min(sa[j][i + j], sc[i + j][j]);
			sy[j - d] = min(sb[j][i + j], sd[i + j][j]);
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 950
memory_kb: 158932
final_rank: 9

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool placex[4096][4096], placey[4096][4096]; short sa[4096][4096], sb[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096];
short rui[128]; uint64_t seq[128];
int popcnt(uint64_t x) {
	int ans = 0;
	while (x) {
		ans += (x & 1);
		x >>= 1;
	}
	return ans;
}
int calc(int N) {
	fill(cnt, cnt + N + 3, 0);
	for (int i = 0; i < N; ++i) {
		++cnt[sy[i] + i + 2];
	}
	for (int i = 0; i <= N; ++i) {
		cnt[i + 2] += cnt[i + 1];
	}
	for (int i = 0; i < N; ++i) {
		ord[cnt[sy[i] + i + 1]++] = i;
	}
	fill(rui, rui + (N >> 6) + 1, 0);
	fill(seq, seq + (N >> 6) + 1, 0);
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			++rui[ord[j] >> 6];
			seq[ord[j] >> 6] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		for (int j = liml; j < limr; ++j) {
			ans += rui[j];
		}
		ans -= __builtin_popcountll(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += __builtin_popcountll(seq[limr] & ((1ULL << (pr & 63)) - 1));
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		placex[x][y] = true;
		placey[y][x] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (placex[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (placey[i][j]) last = j;
			sa[j][i] = min<short>(sa[j][i], j - last);
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (placex[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (placey[i][j]) last = j;
			sb[j][i] = min<short>(sb[j][i], last - j);
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = sa[j][i + j];
			sy[j - d] = sb[j][i + j];
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 96308
final_rank: 4

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool place[4096][4096]; short sa[4096][4096], sb[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096];
short rui[128]; uint64_t seq[128];
int popcnt(uint64_t x) {
	int ans = 0;
	while (x) {
		ans += (x & 1);
		x >>= 1;
	}
	return ans;
}
int calc(int N) {
	fill(cnt, cnt + N + 3, 0);
	for (int i = 0; i < N; ++i) {
		++cnt[sy[i] + i + 2];
	}
	for (int i = 0; i <= N; ++i) {
		cnt[i + 2] += cnt[i + 1];
	}
	for (int i = 0; i < N; ++i) {
		ord[cnt[sy[i] + i + 1]++] = i;
	}
	fill(rui, rui + (N >> 6) + 1, 0);
	fill(seq, seq + (N >> 6) + 1, 0);
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			++rui[ord[j] >> 6];
			seq[ord[j] >> 6] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		for (int j = liml; j < limr; ++j) {
			ans += rui[j];
		}
		ans -= __builtin_popcountll(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += __builtin_popcountll(seq[limr] & ((1ULL << (pr & 63)) - 1));
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		place[x][y] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (place[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (place[j][i]) last = j;
			sa[j][i] = min<short>(sa[j][i], j - last);
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (place[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (place[j][i]) last = j;
			sb[j][i] = min<short>(sb[j][i], last - j);
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = sa[j][i + j];
			sy[j - d] = sb[j][i + j];
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1120
memory_kb: 81988
final_rank: 2

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool place[4096][4096]; short sa[4096][4096], sb[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096];
short bit[128]; uint64_t seq[128];
int calc(int N) {
	fill(cnt, cnt + N + 3, 0);
	for (int i = 0; i < N; ++i) {
		++cnt[sy[i] + i + 2];
	}
	for (int i = 0; i <= N; ++i) {
		cnt[i + 2] += cnt[i + 1];
	}
	for (int i = 0; i < N; ++i) {
		ord[cnt[sy[i] + i + 1]++] = i;
	}
	int upper = (N >> 6) + 1;
	fill(bit, bit + upper + 1, 0);
	fill(seq, seq + upper, 0);
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			int lim = (ord[j] >> 6);
			for (int k = lim + 1; k <= upper; k += k & (-k)) {
				++bit[k];
			}
			seq[lim] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		ans -= __builtin_popcountll(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += __builtin_popcountll(seq[limr] & ((1ULL << (pr & 63)) - 1));
		while (liml != limr) {
			if (liml <= limr) {
				ans += bit[limr];
				limr -= limr & (-limr);
			}
			else {
				ans -= bit[liml];
				liml -= liml & (-liml);
			}
		}
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		place[x][y] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (place[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (place[j][i]) last = j;
			sa[j][i] = min<short>(sa[j][i], j - last);
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (place[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (place[j][i]) last = j;
			sb[j][i] = min<short>(sb[j][i], last - j);
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = sa[j][i + j];
			sy[j - d] = sb[j][i + j];
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1180
memory_kb: 81936
final_rank: 3

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool place[4096][4096]; short sa[4096][4096], sb[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096];
short bit[128]; uint64_t seq[128];
int calc(int N) {
	fill(cnt, cnt + N + 3, 0);
	for (int i = 0; i < N; ++i) {
		++cnt[sy[i] + i + 2];
	}
	for (int i = 0; i <= N; ++i) {
		cnt[i + 2] += cnt[i + 1];
	}
	for (int i = 0; i < N; ++i) {
		ord[cnt[sy[i] + i + 1]++] = i;
	}
	int upper = (N >> 6) + 1;
	fill(bit, bit + upper + 1, 0);
	fill(seq, seq + upper, 0);
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			int lim = (ord[j] >> 6);
			for (int k = lim + 1; k <= upper; k += k & (-k)) {
				++bit[k];
			}
			seq[lim] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		ans -= __builtin_popcount(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += __builtin_popcount(seq[limr] & ((1ULL << (pr & 63)) - 1));
		while (liml != limr) {
			if (liml <= limr) {
				ans += bit[limr];
				limr -= limr & (-limr);
			}
			else {
				ans -= bit[liml];
				liml -= liml & (-liml);
			}
		}
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		place[x][y] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (place[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (place[j][i]) last = j;
			sa[j][i] = min<short>(sa[j][i], j - last);
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (place[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (place[j][i]) last = j;
			sb[j][i] = min<short>(sb[j][i], last - j);
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = sa[j][i + j];
			sy[j - d] = sb[j][i + j];
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 0.06666666666666667
time_ms: 890
memory_kb: 67172
final_rank: 18

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool place[4096][4096]; short sa[4096][4096], sb[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096];
short bit[128]; uint64_t seq[128];
int popcnt(uint64_t x) {
	int ans = 0;
	while (x) {
		ans += (x & 1);
		x >>= 1;
	}
	return ans;
}
int calc(int N) {
	fill(cnt, cnt + N + 3, 0);
	for (int i = 0; i < N; ++i) {
		++cnt[sy[i] + i + 2];
	}
	for (int i = 0; i <= N; ++i) {
		cnt[i + 2] += cnt[i + 1];
	}
	for (int i = 0; i < N; ++i) {
		ord[cnt[sy[i] + i + 1]++] = i;
	}
	int upper = (N >> 6) + 1;
	fill(bit, bit + upper + 1, 0);
	fill(seq, seq + upper, 0);
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			int lim = (ord[j] >> 6);
			for (int k = lim + 1; k <= upper; k += k & (-k)) {
				++bit[k];
			}
			seq[lim] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		for (int j = liml; j >= 1; j -= j & (-j)) {
			ans -= bit[j];
		}
		for (int j = limr; j >= 1; j -= j & (-j)) {
			ans += bit[j];
		}
		ans -= popcnt(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += popcnt(seq[limr] & ((1ULL << (pr & 63)) - 1));
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		place[x][y] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (place[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (place[j][i]) last = j;
			sa[j][i] = min<short>(sa[j][i], j - last);
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (place[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (place[j][i]) last = j;
			sb[j][i] = min<short>(sb[j][i], last - j);
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = sa[j][i + j];
			sy[j - d] = sb[j][i + j];
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1590
memory_kb: 82068
final_rank: 6

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool place[4096][4096]; short sa[4096][4096], sb[4096][4096], sx[4096], sy[4096], cnt[4096], ord[4096];
short rui[128]; uint64_t seq[128];
int popcnt(uint64_t x) {
	int ans = 0;
	while (x) {
		ans += (x & 1);
		x >>= 1;
	}
	return ans;
}
int calc(int N) {
	fill(cnt, cnt + N + 3, 0);
	for (int i = 0; i < N; ++i) {
		++cnt[sy[i] + i + 2];
	}
	for (int i = 0; i <= N; ++i) {
		cnt[i + 2] += cnt[i + 1];
	}
	for (int i = 0; i < N; ++i) {
		ord[cnt[sy[i] + i + 1]++] = i;
	}
	fill(rui, rui + (N >> 6) + 1, 0);
	fill(seq, seq + (N >> 6) + 1, 0);
	int ans = 0;
	for (int i = N - 1; i >= 0; --i) {
		for (int j = cnt[i + 2] - 1; j >= cnt[i + 1]; --j) {
			++rui[ord[j] >> 6];
			seq[ord[j] >> 6] |= 1ULL << (ord[j] & 63);
		}
		int pl = max(i - sx[i], 0), pr = max(i - L + 2, pl);
		if (pl == pr) continue;
		int liml = (pl >> 6), limr = (pr >> 6);
		for (int j = liml; j < limr; ++j) {
			ans += rui[j];
		}
		ans -= popcnt(seq[liml] & ((1ULL << (pl & 63)) - 1));
		ans += popcnt(seq[limr] & ((1ULL << (pr & 63)) - 1));
	}
	return ans;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		place[x][y] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (place[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (place[j][i]) last = j;
			sa[j][i] = min<short>(sa[j][i], j - last);
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (place[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (place[j][i]) last = j;
			sb[j][i] = min<short>(sb[j][i], last - j);
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0), cnt = 0;
		for (int j = d; j < H && i + j < W; ++j) {
			sx[j - d] = sa[j][i + j];
			sy[j - d] = sb[j][i + j];
			++cnt;
		}
		ans += calc(cnt);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1490
memory_kb: 81936
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
int H, W, L, P;
bool place[4096][4096]; short sa[4096][4096], sb[4096][4096], sx[4096], sy[4096];
int calc(int N) {
	int ans = 0;
	for (int i = 0; i < N; ++i) {
		for (int j = i - sx[i]; j < i - L + 2; ++j) {
			if (sy[j] + j > i) {
				++ans;
			}
		}
	}
	return ans;
}
int main() {
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; ++i) {
		int x, y;
		cin >> x >> y; --x, --y;
		place[x][y] = true;
	}
	short last;
	for (int i = 0; i < H; ++i) {
		last = -1;
		for (int j = 0; j < W; ++j) {
			if (place[i][j]) last = j;
			sa[i][j] = j - last;
		}
	}
	for (int i = 0; i < W; ++i) {
		last = -1;
		for (int j = 0; j < H; ++j) {
			if (place[j][i]) last = j;
			sa[j][i] = min<short>(sa[j][i], j - last);
		}
	}
	for (int i = H - 1; i >= 0; --i) {
		last = W;
		for (int j = W - 1; j >= 0; --j) {
			if (place[i][j]) last = j;
			sb[i][j] = last - j;
		}
	}
	for (int i = W - 1; i >= 0; --i) {
		last = H;
		for (int j = H - 1; j >= 0; --j) {
			if (place[j][i]) last = j;
			sb[j][i] = min<short>(sb[j][i], last - j);
		}
	}
	long long ans = 0;
	for (int i = -(H - 1); i <= (W - 1); ++i) {
		int d = max(-i, 0);
		for (int j = d; j < H; ++j) {
			sx[j - d] = sa[j][i + j];
			sy[j - d] = sb[j][i + j];
		}
		ans += calc(H - d);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 0.06666666666666667
time_ms: 7490
memory_kb: 67048
final_rank: 20

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>
#include <set>

class Bit {
	std::vector<int>vec;
public:
	Bit(int size) : vec(size, 0){};
	int get(int position) const {
		int result = 0;
		while (position >= 0) {
			result += vec[position];
			position -= (position + 1) & ~position;
		}
		return result;
	}
	void add(int position, int value) {
		while (position < vec.size()) {
			vec[position] += value;
			position += (position + 1) & ~position;
		}
	}
	void clear() {
		std::fill(vec.begin(), vec.end(), 0);
	}
};
int main(void) {
	int height, width, min_size, p; std::cin >> height >> width >> min_size >> p;
	std::vector<std::vector<int>> for_top(height, std::vector<int>(width, 1));
	for (auto i = 0; i < p; ++i) {
		int a, b; std::cin >> a >> b;
		for_top[--a][--b] = 0;
	}
	auto for_bottom = for_top; auto for_right = for_top; auto for_left = for_top;
	for (auto i = 1; i < height; ++i) {
		for (auto j = 0; j < width; ++j) {
			if (for_top[i][j] != 0) {
				for_top[i][j] += for_top[i - 1][j];
			}
			if (for_bottom[height - i - 1][j] != 0) {
				for_bottom[height - i - 1][j] += for_bottom[height - i][j];
			}
		}
	}
	for (auto i = 0; i < height; ++i) {
		for (auto j = 1; j < width; ++j) {
			if (for_left[i][j] != 0) {
				for_left[i][j] += for_left[i][j - 1];
			}
			if (for_right[i][width - j - 1] != 0) {
				for_right[i][width - j - 1] += for_right[i][width - j];
			}
		}
	}
	std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::function<bool(std::pair<int, int>&, std::pair<int, int>&)>> history([](std::pair<int, int>& a, std::pair<int, int>& b) {return a.first > b.first; });
	Bit bit(std::min(height, width) + 1);
	long long int count = 0;
	for (int i = -width + 1; i < height; ++i) {
		const int h = std::max(i, 0);
		const int w = std::max(0, h - i);
		for (auto j = 0; h + j < height && w + j < width; ++j) {
			const auto for_next = std::min(for_bottom[h + j][w + j], for_right[h + j][w + j]);
			if (for_next >= min_size) {
				history.emplace(j + for_next - 1, j);
				bit.add(j, 1);
			}
			const auto for_prev = std::min(for_top[h + j][w + j], for_left[h + j][w + j]);
			if (for_prev >= min_size) {
				count += bit.get(j + 1 - min_size) - bit.get(j - for_prev);
			}
			while (!history.empty() && history.top().first == j) {
				bit.add(history.top().second, -1);
				history.pop();
			}
		}
	}
	std::cout << count << '\n';
}
accuracy: 1
time_ms: 3130
memory_kb: 253752
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>
#include <set>

class Bit {
	std::vector<int>vec;
public:
	Bit(int size) : vec(size, 0){};
	int get(int position) const {
		int result = 0;
		while (position >= 0) {
			result += vec[position];
			position -= (position + 1) & ~position;
		}
		return result;
	}
	void add(int position, int value) {
		while (position < vec.size()) {
			vec[position] += value;
			position += (position + 1) & ~position;
		}
	}
	void clear() {
		std::fill(vec.begin(), vec.end(), 0);
	}
};
int main(void) {
	int height, width, min_size, p; std::cin >> height >> width >> min_size >> p;
	std::vector<std::vector<int>> for_top(height, std::vector<int>(width, 1));
	for (auto i = 0; i < p; ++i) {
		int a, b; std::cin >> a >> b;
		for_top[--a][--b] = 0;
	}
	auto for_bottom = for_top; auto for_right = for_top; auto for_left = for_top;
	for (auto i = 1; i < height; ++i) {
		for (auto j = 0; j < width; ++j) {
			if (for_top[i][j] != 0) {
				for_top[i][j] += for_top[i - 1][j];
			}
			if (for_bottom[height - i - 1][j] != 0) {
				for_bottom[height - i - 1][j] += for_bottom[height - i][j];
			}
		}
	}
	for (auto i = 0; i < height; ++i) {
		for (auto j = 1; j < width; ++j) {
			if (for_left[i][j] != 0) {
				for_left[i][j] += for_left[i][j - 1];
			}
			if (for_right[i][width - j - 1] != 0) {
				for_right[i][width - j - 1] += for_right[i][width - j];
			}
		}
	}
	std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::function<bool(std::pair<int, int>&, std::pair<int, int>&)>> history([](std::pair<int, int>& a, std::pair<int, int>& b) {return a.first > b.first; });
	Bit bit(std::min(height, width) + 1);
	long long int count = 0;
	for (int i = -height + 1; i < height; ++i) {
		const int h = std::max(i, 0);
		const int w = std::max(0, h - i);
		for (auto j = 0; h + j < height && w + j < width; ++j) {
			const auto for_next = std::min(for_bottom[h + j][w + j], for_right[h + j][w + j]);
			if (for_next >= min_size) {
				history.emplace(j + for_next - 1, j);
				bit.add(j, 1);
			}
			const auto for_prev = std::min(for_top[h + j][w + j], for_left[h + j][w + j]);
			if (for_prev >= min_size) {
				count += bit.get(j + 1 - min_size) - bit.get(j - for_prev);
			}
			while (!history.empty() && history.top().first == j) {
				bit.add(history.top().second, -1);
				history.pop();
			}
		}
	}
	std::cout << count << '\n';
}
accuracy: 0.13333333333333333
time_ms: 1770
memory_kb: 253628
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 4001

enum Type{
	LEFT_UP,
	RIGHT_UNDER,
};

struct Info{
	Info(Type arg_type,short arg_max_len,short arg_loc){
		type = arg_type;
		max_len = arg_max_len;
		loc = arg_loc; //★★斜めのラインにおける相対位置★★
	}
	bool operator<(const struct Info &arg) const{
		if(max_len != arg.max_len){ //最大長の降順
			return max_len > arg.max_len;
		}else{

			return type < arg.type; //長さが同じなら、LEFT_UPを左に持ってくる
		}
	}
	Type type;
	short max_len,loc;
};

int H,W,min_len,P;
int BIT_MAX;
short LIMIT[2][NUM][NUM];
int BIT[2][NUM];
bool table[NUM][NUM];
short dp[NUM][NUM];


void add(Type type,int loc,int value){

	BIT[type][loc] += value;

	loc += loc & -loc; //最後の1ビットを足した場所が次の★更新★場所

	while(loc <= BIT_MAX){
		BIT[type][loc] += value;
		loc += loc & -loc;
	}
}

int getSum(Type type,int loc){

	int sum = BIT[type][loc];

	loc -= loc & -loc; //最後の1ビットを引いた場所が次の★加算★場所

	while(loc > 0){
		sum += BIT[type][loc];
		loc -= loc & -loc;
	}
	return sum;
}

int calc(Type type,int left,int right){ //left～rightの区間の総和を、sum(1～right)-sum(1～left-1)で求める
	return getSum(type,right)-getSum(type,left-1);
}

void init_LIMIT(Type type){
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			LIMIT[type][row][col] = NUM;
		}
	}
}

void update_LIMIT(Type type){
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			LIMIT[type][row][col] = min(LIMIT[type][row][col],dp[row][col]);
		}
	}
}

bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1){
		return true;
	}else{
		return false;
	}
}

int main(){

	scanf("%d %d %d %d",&H,&W,&min_len,&P);

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			table[row][col] = true;
		}
	}

	int tmp_row,tmp_col;

	for(int loop = 0; loop < P; loop++){

		scanf("%d %d",&tmp_row,&tmp_col);
		tmp_row--;
		tmp_col--;
		table[tmp_row][tmp_col] = false;
	}

	/*★各場所からの最大長を計算する★*/

	/*左上基準*/
	init_LIMIT(LEFT_UP);

	//右方向への最大長さ
	for(int row = 0; row < H; row++){
		if(table[row][W-1]){
			dp[row][W-1] = 1;
		}else{
			dp[row][W-1] = 0;
 		}
	}

	for(int col = W-2; col >= 0; col--){
		for(int row = 0; row < H; row++){
			if(table[row][col]){
				dp[row][col] = dp[row][col+1]+1;
			}else{
				dp[row][col] = 0;
			}
		}
	}
	update_LIMIT(LEFT_UP);

	//下方向への最大長さ
	for(int col = 0; col < W; col++){
		if(table[H-1][col]){
			dp[H-1][col] = 1;
		}else{
			dp[H-1][col] = 0;
		}
	}

	for(int row = H-2; row >= 0; row--){
		for(int col = 0; col < W; col++){
			if(table[row][col]){
				dp[row][col] = dp[row+1][col]+1;
			}else{
				dp[row][col] = 0;
			}
		}
	}
	update_LIMIT(LEFT_UP);

	/*右下基準*/
	init_LIMIT(RIGHT_UNDER);

	//左方向への最大長さ
	for(int row = 0; row < H; row++){
		if(table[row][0]){
			dp[row][0] = 1;
		}else{
			dp[row][0] = 0;
		}
	}

	for(int col = 1; col < W; col++){
		for(int row = 0; row < H; row++){
			if(table[row][col]){
				dp[row][col] = dp[row][col-1]+1;
			}else{
				dp[row][col] = 0;
			}
		}
	}
	update_LIMIT(RIGHT_UNDER);

	//上方向への最大長さ
	for(int col = 0; col < W; col++){
		if(table[0][col]){
			dp[0][col] = 1;
		}else{
			dp[0][col] = 0;
		}
	}

	for(int row = 1; row < H; row++){
		for(int col = 0; col < W; col++){
			if(table[row][col]){
				dp[row][col] = dp[row-1][col]+1;
			}else{
				dp[row][col] = 0;
			}
		}
	}
	update_LIMIT(RIGHT_UNDER);


	vector<Info> V;
	ll ans = 0;

	//斜めのラインごとに計上処理を行う
	int start_row = 0,start_col = W-2;
	int left,right;

	while(true){

		V.clear();
		BIT_MAX = 0;

		tmp_row = start_row,tmp_col = start_col;
		//斜めのラインのデータを走査する
		while(rangeCheck(tmp_row,tmp_col)){

			//★★BIT木は1オリジン★★
			V.push_back(Info(LEFT_UP,LIMIT[LEFT_UP][tmp_row][tmp_col],BIT_MAX+1));
			V.push_back(Info(RIGHT_UNDER,LIMIT[RIGHT_UNDER][tmp_row][tmp_col],BIT_MAX+1));

			tmp_row++;
			tmp_col++;
			BIT_MAX++;
		}

		sort(V.begin(),V.end());

		//BIT木の初期化
		for(int i = 0; i <= BIT_MAX; i++){
			BIT[LEFT_UP][i] = 0;
			BIT[RIGHT_UNDER][i] = 0;
		}

		//最大長が大きい方から、降順に処理する(★★既に1が立っている場所の最大長は、必ず基準の最大長以上となる★★)
		for(int i = 0; i < V.size(); i++){
			if(V[i].type == LEFT_UP){
				//右方向にある範囲を見に行く
				left = (int)V[i].loc+min_len-1;
				right = (int)(V[i].loc+V[i].max_len)-1;

				if(left <= right){
					ans += calc(RIGHT_UNDER,left,right); //ペアになるものを探す
				}

			}else{ //V[i].type == RIGHT_UNDER
				//左方向にある範囲を見に行く
				right = (int)V[i].loc-min_len+1;
				left = (int)(V[i].loc-V[i].max_len)+1;

				if(left <= right){
					ans += calc(LEFT_UP,left,right);
				}
			}

			add(V[i].type,V[i].loc,1);
		}

		if(start_row == H-2 && start_col == 0){
			break;
		}

		if(start_row == 0){

			if(start_col != 0){

				start_col--;

			}else{

				start_row++;
			}

		}else{ //start_col == 0

			start_row++;
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 3060
memory_kb: 112780
final_rank: 14

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<unordered_set>
#define Min(a,b) a=min(a,b);
#define lol(i,n) for(ll i=0;i<n;i++)
#define mod 1000000007
typedef long long ll;

using namespace std;
#define H 4010
#define N (1<<12)
class RSQ{
private:
    ll dat[N*2];
    ll dfs(int l,int r,int a,int b,int k){
	if(l<=a&&b<=r)return dat[k];
	if(b<=l||r<=a)return 0;
	int vl=dfs(l,r,a,(a+b)/2,k*2+1);
	int vr=dfs(l,r,(a+b)/2,b,k*2+2);
	return vl+vr;
    }
public:
    void Init(){
	lol(i,2*N)dat[i]=0;
    }
    void Update(int i,int x){
	i+=N-1;
	dat[i]=x;
	while(i>0){
	    i=(i-1)/2;
	    dat[i]=dat[i*2+1]+dat[i*2+2];
	}
    }
    ll Sum(int l,int r){
	if(r>N-2)r=N-2;
	if(l>r)return 0;
	return dfs(l,r+1,0,N,0);
    }
};
ll h,w,p,q;
//bool t[H][H];
unordered_set<int> st[H];
ll f[H][H],g[H][H];
int main(){
    cin>>h>>w>>q>>p;
    lol(i,h)lol(j,w)f[i][j]=g[i][j]=mod;
    lol(i,p){int y,x;cin>>y>>x;st[y-1].insert(x-1);}
    lol(i,h){
	ll cnt=-1;
	lol(j,w){
	    if(st[i].find(j)!=st[i].end())cnt=-1;
	    else cnt++;
	    Min(g[i][j],cnt);
	}
	cnt=-1;
	for(int j=w-1;j>=0;j--){
	    if(st[i].find(j)!=st[i].end())cnt=-1;
	    else cnt++;
	    Min(f[i][j],cnt);
	}
    }
    lol(j,w){
	ll cnt=-1;
	lol(i,h){
	    if(st[i].find(j)!=st[i].end())cnt=-1;
	    else cnt++;
	    Min(f[i][j],cnt);
	}
	cnt=-1;
	for(int i=h-1;i>=0;i--){
	    if(st[i].find(j)!=st[i].end())cnt=-1;
	    else cnt++;
	    Min(g[i][j],cnt);
	}
    }
    ll ans=0;
    lol(r,h+w-1){
	int sy,sx;
	if(r<h)sy=r,sx=0;
	else sy=h-1,sx=r-h+1;
	ll n=min(min(r+1,h+w-1-r),min(h,w));
	vector<pair<ll,ll> >v;
	lol(i,n){
	    int y=sy-i,x=sx+i;
	    if(g[y][x]==-1)continue;
	    v.push_back(make_pair(i-g[y][x],i));
	}
	sort(v.begin(),v.end());
	int last=0;
	RSQ seg;seg.Init();
	lol(i,n){
	    int y=sy-i,x=sx+i;
	    if(f[y][x]==-1)continue;
	    while(last<v.size()){
		if(v[last].first<=i){
		    seg.Update(v[last].second,1);
		    last++;
		}
		else break;
	    }
	    ans+=seg.Sum(i+q-1,i+f[y][x]);
	}
    }
    cout<<ans<<endl;
    return 0;
}
accuracy: 1
time_ms: 3880
memory_kb: 258424
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;

struct BIT{
  int t[5000];
  void init(){
    for(int i=0;i<5000;i++){
      t[i]=0;
    }
  }
  void add(int i,int x){
    i+=10;
    
    while( i<5000 ){
      t[i]+=x;
      i+=(i&-i);
    }
  }
  int sum(int i){
    i+=10;
    
    int res=0;
    while(i>0){
      res+=t[i];
      i-=(i&-i);
    }
    return res;
  }
};

BIT T;
int H,W,L,P;
short t[4000][4000];

short A[4000][4000];
short B[4000][4000];
short C[4000][4000];
short D[4000][4000];

vector< short > G[5000];

ll solve(int y,int x){
  for(int i=0;i<5000;i++)G[i].clear();
  T.init();
  
  ll res=0;
  
  for(int i=0;i<5000;i++){
    int py=y+i;
    int px=x+i;
    if(py>=H || px>=W)break;
    if(i-L+1>=0){
      int ay=py-L+1;
      int ax=px-L+1;

      int len = min( C[ay][ax], D[ay][ax]) - 1;
      
      if(i-L+1+len>=i){
        T.add( i-L+1 , 1 );
        G[ i-L+1 + len  ].push_back( i-L+1 );
      }
      
    }

    int fr=min(A[py][px],B[py][px]);
    
    if(fr>=3){
      ll v = T.sum(4500) - T.sum(i-fr);
      res+=v;
    }
    
    for(int j=0;j<(int)G[i].size();j++){
      T.add( G[i][j], -1 );
    }
  }

  return res;
}

int main(){

  scanf("%d %d %d %d",&H,&W,&L,&P);
  for(int i=0;i<P;i++){
    int y,x;
    scanf("%d %d",&y,&x);
    y--,x--;
    
    t[y][x]=1;
  }
  
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      if(t[i][j]==1){
        A[i][j]=0;
        continue;
      }
      A[i][j]=1;
      if(j>0){
        A[i][j]+=A[i][j-1];
      }
    }
  }
  
  for(int j=0;j<W;j++){  
    for(int i=0;i<H;i++){
      if(t[i][j]==1){
        B[i][j]=0;
        continue;
      }
      B[i][j]=1;
      if(i>0){
        B[i][j]+=B[i-1][j];
      }
    }
  }

  
  for(int i=0;i<H;i++){
    for(int j=W-1;j>=0;j--){
      if(t[i][j]==1){
        C[i][j]=0;
        continue;
      }
      C[i][j]=1;
      if(j+1<W){
        C[i][j]+=C[i][j+1];
      }
    }
  }
  
  for(int j=0;j<W;j++){  
    for(int i=H-1;i>=0;i--){
      if(t[i][j]==1){
        D[i][j]=0;
        continue;
      }
      D[i][j]=1;
      if(i+1<H){
        D[i][j]+=D[i+1][j];
      }
    }
  }

  ll ans=0;
  for(int i=0;i<H;i++){
    ans+= solve(i,0);
  }
  for(int i=1;i<W;i++){
    ans+= solve(0,i);
  }
  
  printf("%lld\n",ans);
  return 0;
}
accuracy: 1
time_ms: 1790
memory_kb: 157496
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define ll long long
using namespace std;

typedef pair<int,int> P;

int bit[4010];

void add(int i,int x){
	while(i < 4010){
		bit[i] += x;
		i += i & -i;
	}
}

ll get(int i){
	ll s = 0;
	while(i){
		s += bit[i];
		i -= i & -i;
	}
	return s;
}

int h,w,l,p,lu[4000][4000],rd[4000][4000];
ll ans = 0;
bool field[4000][4000] = {};

signed main(){
	cin >> h >> w >> l >> p;
	for(int i = 0;i < p;i++){
		int a,b;
		cin >> a >> b; a--;b--;
		field[a][b] = true;
	}
	for(int i = 0;i < h;i++){
		int cnt = 0;
		for(int j = 0;j < w;j++){
			if(field[i][j]) cnt = 0;
			else cnt++;
			lu[i][j] = cnt;
		}
		cnt = 0;
		for(int j = w - 1;j >= 0;j--){
			if(field[i][j]) cnt = 0;
			else cnt++;
			rd[i][j] = cnt;
		}
	}
	for(int i = 0;i < w;i++){
		int cnt = 0;
		for(int j = 0;j < h;j++){
			if(field[j][i]) cnt = 0;
			else cnt++;
			lu[j][i] = min(cnt,lu[j][i]);
		}
		cnt = 0;
		for(int j = h - 1;j >= 0;j--){
			if(field[j][i]) cnt = 0;
			else cnt++;
			rd[j][i] = min(cnt,rd[j][i]);
		}
	}
	for(int i = -h + 1;i <= w - 1;i++){
		for(int j = 0;j < h;j++) bit[j + 1] = 0;
		vector<int> vec[4010];
		for(int j = 0;j < h;j++){
			if(i + j >= 0 && i + j < w && lu[j][i + j]) vec[j - lu[j][i + j] + 1].push_back(j);
		}
		for(int j = 0;j < h;j++){
			for(int v : vec[j]) add(v + 1,1);
			if(i + j >= 0 && i + j < w && rd[j][i + j] && j + rd[j][i + j] > j + l - 1) ans += get(j + rd[j][i + j]) - get(j + l - 1);
		}
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2070
memory_kb: 142884
final_rank: 12

code_snippet: #include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int H, W, L, P, bit[4009]; bool used[4009][4009]; int lx[4009][4009], rx[4009][4009];
void add(int p, int x) {
	p++;
	while (p <= 4009) { bit[p] += x; p += (p&-p); }
}
int sum(int p) {
	int s = 0; p++;
	while (p >= 1) { s += bit[p]; p -= (p&-p); }
	return s;
}
int main() {
	cin >> H >> W >> L >> P;
	for (int i = 0; i < P; i++) { int a, b; cin >> a >> b; used[a][b] = true; }
	for (int i = 0; i < 4009; i++) { for (int j = 0; j < 4009; j++) { lx[i][j] = 999999; rx[i][j] = 999999; } }
	for (int i = 1; i <= H; i++) {
		int s = 0;
		for (int j = 1; j <= W; j++) {
			if (used[i][j] == true)s = 0; else s++;
			rx[i][j] = min(rx[i][j], s);
		}
		s = 0;
		for (int j = W; j >= 1; j--) {
			if (used[i][j] == true)s = 0; else s++;
			lx[i][j] = min(lx[i][j], s);
		}
	}
	for (int i = 1; i <= W; i++) {
		int s = 0;
		for (int j = 1; j <= H; j++) {
			if (used[j][i] == true)s = 0; else s++;
			rx[j][i] = min(rx[j][i], s);
		}
		s = 0;
		for (int j = H; j >= 1; j--) {
			if (used[j][i] == true)s = 0; else s++;
			lx[j][i] = min(lx[j][i], s);
		}
	}
	int Z = max(H, W); long long ans = 0;
	for (int i = -Z; i <= Z; i++) {
		vector<pair<int, int>>V;
		for (int j = 1; j <= H; j++) {
			int cx = j, cy = j + i; if (cy <= 0 || cy > W)continue;
			V.push_back(make_pair(cx, cy));
		}
		if (V.size() < L)continue;
		vector<pair<int, int>>U;
		for (int j = 0; j < V.size(); j++) {
			U.push_back(make_pair(rx[V[j].first][V[j].second] - j, j));
		}
		sort(U.begin(), U.end(), greater<pair<int, int>>());
		int cx = 0;
		for (int j = 0; j < 4009; j++)bit[j] = 0;
		for (int j = 0; j < V.size(); j++) {
			while (cx < U.size() && U[cx].first >= -j) { add(U[cx].second, 1); cx++; }
			int l = j + L - 1, r = j + lx[V[j].first][V[j].second] - 1;
			if (l > r)continue;
			ans += sum(r) - sum(l - 1);
		}
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2040
memory_kb: 143396
final_rank: 11

code_snippet: #include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cmath>
#include <iomanip>
#include <cassert>
#include <bitset>
using namespace std;

typedef pair<int, int> P;
#define rep(i, n) for (int i=0; i<(n); i++)
#define all(c) (c).begin(), (c).end()
#define uniq(c) c.erase(unique(all(c)), (c).end())
#define index(xs, x) (int)(lower_bound(all(xs), x) - xs.begin())
#define _1 first
#define _2 second
#define pb push_back
#define INF 1145141919
#define MOD 1000000007
bool S[4000];
int B[4001];
void BIT_add(int i) {
  for (int x=i+1; x<=4000; x+=x&-x) B[x]++;
}
int BIT_sum(int i) {
  int s = 0;
  for (int x=i+1; x>0; x-=x&-x) s += B[x];
  return s;
}

int H, W, L, N;
vector<int> GX[4000], GY[4000];
int GXh[4000], GYh[4000];

signed main() {
  ios::sync_with_stdio(false); cin.tie(0);
  cin >> H >> W >> L >> N;
  rep(i, N) {
    int x, y;
    cin >> y >> x;
    x--, y--;
    GX[y].pb(x);
    GY[x].pb(y);
  }
  rep(y, H) sort(all(GX[y]));
  rep(x, W) sort(all(GY[x]));

  long long ctr = 0;
  for (int d=1-H; d<W; d++) {
    int bx = 0, by = 0;
    if (d < 0) by = -d;
    else bx = d;
    int len = min(H-by, W-bx);
    rep(x, W) GYh[x] = (int)GY[x].size()-1;
    rep(y, H) GXh[y] = (int)GX[y].size()-1;
    rep(i, 4000) S[i] = 0;
    rep(i, 4001) B[i] = 0;
    auto add = [&](int x, int y) {
      int s = max(x-bx, y-by);
      if (S[s]) return;
      S[s] = 1;
      BIT_add(s);
    };

    for (int s=len-1; s>=0; s--) {
      int x = bx+s, y = by+s;
      int mx = W, my = H;
      while (GXh[y] >= 0 && GX[y][GXh[y]] >= x) add(mx=GX[y][GXh[y]--], y);
      while (GYh[x] >= 0 && GY[x][GYh[x]] >= y) add(x, my=GY[x][GYh[x]--]);
      int X = min(mx-bx, my-by);
      // count [s+L-1, X)
      if (s+L-1 >= X) continue;
      //cout<< "("<<x<<","<<y<<"): ["<<s+L-1<<","<<X<<") | "; rep(i, W) cout<<S[i]<<",";cout<<"\n";
      //for (int p=s+L-1; p<X; p++) ctr += 1-S[p];
      ctr += (X-(s+L-1)) - (BIT_sum(X-1) - BIT_sum(s+L-2));
    }
  }
  cout << ctr << "\n";
  return 0;
}
accuracy: 1
time_ms: 1740
memory_kb: 4668
final_rank: 1

code_snippet: #include <bits/stdc++.h>
    using namespace std;
    using LL = long long;

    short H,W,L;
    int P;

    const int N_MAX = 4001;

    short la[N_MAX][N_MAX];
    short ra[N_MAX][N_MAX];
    short ua[N_MAX][N_MAX];
    short da[N_MAX][N_MAX];

    struct BIT{
    	vector<int>seg;
    	int width;
    	BIT(int n):width(1){
    		while(width < n)width *= 2;
    		seg.resize(width + 1);
    	}
    	void add(int x,int val){
    		x++;
    		while(x <= width){
    			seg[x] += val;
    			x += (x & -x);
    		}
    	}
    	int range(int x){
    		int res = 0;
    		while(x > 0){
    			res += seg[x];
    			x -= (x & -x);
    		}
    		return res;
    	}
    };

    int main(){
    	cin >> H >> W >> L >> P;
    	for(int i = 0;i < H;++i){
    		for(int j = 0;j < W;++j){
    			la[i][j] = ra[i][j] = ua[i][j] = da[i][j] = 6666;
    		}
    	}
    	for(int i = 0;i < P;++i){
    		short a,b;
    		cin >> a >> b;
    		--a;--b;
    		la[a][b] = ra[a][b] = ua[a][b] = da[a][b] = 0;
    	}
    	for(int i = 0;i < H;++i){
    		for(int j = 0;j < W;++j){
    			la[i][j] = min(la[i][j],(short)((j)?(la[i][j-1]+(short)1):(short)1));
    		}
    	}
    	for(int i = 0;i < H;++i){
    		for(int j = W - 1;j >= 0;--j){
    			ra[i][j] = min(ra[i][j],(short)(ra[i][j+1]+(short)1));
    		}
    	}
    	for(int i = 0;i < H;++i){
    		for(int j = 0;j < W;++j){
    			ua[i][j] = min(ua[i][j],(short)((i)?(ua[i-1][j]+(short)1):(short)1));
    		}
    	}
    	for(int i = H - 1;i >= 0;--i){
    		for(int j = 0;j < W;++j){
    			da[i][j] = min(da[i][j],(short)(da[i+1][j]+(short)1));
    		}
    	}
    	for(int i = 0;i < H;++i){
    		for(int j = 0;j < W;++j){
    			ra[i][j] = min(ra[i][j],da[i][j]);
    		}
    	}
    	for(int i = 0;i < H;++i){
    		for(int j = 0;j < W;++j){
    			la[i][j] = min(la[i][j],ua[i][j]);
    		}
    	}
    	vector<vector<short>>pos(H),neg(W-1);
    	vector<vector<short>>pro(H),nro(W-1);
    	for(int i = 0;i < H;++i){
    		for(int j = 0;j < W;++j){
    			if(i - j >= 0){
    				pos[i - j].push_back(la[i][j]-pos[i - j].size()-1);
    				pro[i - j].push_back(ra[i][j]);
    			}else{
    				neg[j - i - 1].push_back(la[i][j]-pos[j - i - 1].size()-1);
    				nro[j - i - 1].push_back(ra[i][j]);
    			}
    		}
    	}
    	long long ans = 0;

    	for(int k = 0;k < H;++k){
    		BIT bit(pos.size());
    		priority_queue<pair<int,int>>que;
    		for(int i = 0;i < pos[k].size();++i){
    			que.push(make_pair((int)pos[k][i],i));
    		}
    		for(int i = 0;i < pos[k].size();++i){
    			while(!que.empty() && que.top().first >= -i){
    				bit.add(que.top().second,1);
    				que.pop();
    			}
    			int dn = i + L - 1;dn = min(dn,(int)pos[k].size());
    			int up = i + pro[k][i];
    			if(dn < up){
    				int ub = bit.range(up);
    				int db = bit.range(dn);
    				int can = ub - db;
    				ans += (long long)can;
    			}
    		}
    	}

    	for(int k = 0;k < W-1;++k){
    	    BIT bit(neg.size());
    	    priority_queue<pair<int,int>>que;
    	    for(int i = 0;i < neg[k].size();++i){
    	    	que.push(make_pair((int)neg[k][i],i));
    	    }
    	    for(int i = 0;i < neg[k].size();++i){
    	    	while(!que.empty() && que.top().first >= -i){
    	   			bit.add(que.top().second,1);
    	   			que.pop();
    	    	}
    	    	int dn = i + L - 1;dn = min(dn,(int)neg[k].size());
    	   		int up = i + nro[k][i];
    	    	if(dn < up){
    	    		int can = bit.range(up) - bit.range(dn);
    	    		ans += (long long)can;
    	   		}
    	   	}
    	}
    	cout << ans << endl;
    	return 0;
    }
accuracy: 0.06666666666666667
time_ms: 1850
memory_kb: 213088
final_rank: 19