// URL: https://yukicoder.me/problems/no/655 import std.algorithm, std.array, std.container, std.math, std.range, std.typecons, std.string; version(unittest) {} else void main() { int N, K; long P; io.getV(N, K, P); Point[] b; io.getS!("x", "y")(K, b); foreach (ref bi; b) { --bi.x; --bi.y; } if (N == 1) { io.put(0); return; } auto a = kaidan!long(N); foreach (ref ai; a) ai[] = -1; auto q = DList!Point(b); auto dp = [Point(-1, -1), Point(-1, 0), Point(0, -1), Point(0, 1), Point(1, 0), Point(1, 1)]; foreach (ref bi; b) a[bi.x][bi.y] = 0; while (!q.empty) { auto pp = q.front; q.removeFront; foreach (dpi; dp) { auto np = pp + dpi; if (np.x < 0 || np.x >= N || np.y < 0 || np.y > np.x || a[np.x][np.y] >= 0) continue; a[np.x][np.y] = a[pp.x][pp.y] + 1; q.insertBack(np); } } auto as = kaidan!long(N+1); foreach_reverse (i; 0..N) foreach (j; 0..i+1) { as[i][j] = as[i+1][j] + as[i+1][j+1] + a[i][j]; if (i < N-1) as[i][j] -= as[i+2][j+1]; } auto bs = kaidan2!long(N+1); foreach_reverse (i; 0..N) foreach (j; 0..i+1) bs[i][j+1] = bs[i][j]+bs[i+1][j+1]-bs[i+1][j]+a[i][j]; auto calc(int i, int j, int e) { if (e == 0) return a[i][j]; else return as[i][j]-as[i+e+1][j+e+1]-bs[i+e+1][j+e+1]+bs[i+e+1][j]; } auto e = kaidan!int(N); foreach (j; 0..N) e[N-1][j] = as[N-1][j] >= P ? 0 : 1; foreach_reverse (i; 0..N-1) foreach (j; 0..i+1) { auto r = min(e[i+1][j], e[i+1][j+1]); while (r >= 0 && calc(i, j, r) >= P) --r; e[i][j] = r+1; } auto ans = 0L; foreach (i; 0..N) foreach (j; 0..i+1) ans += N-(e[i][j]+i); io.put(ans); } auto kaidan(T)(int n) { auto a = new T[][](n); foreach (i; 0..n) a[i] = new T[](i+1); return a; } auto kaidan2(T)(int n) { auto a = new T[][](n); foreach (i; 0..n) a[i] = new T[](i+2); return a; } alias Point = Point2!int; struct Point2(T) { alias P = Point2!T, Op = string; T x, y; pure P opBinary(Op o)(P r) if (o=="+"||o=="-") { return mixin("P(x"~o~"r.x, y"~o~"r.y)"); } P opOpAssign(Op o)(P r) if (o=="+"||o=="-") { mixin("x"~o~"=r.x; y"~o~"=r.y;"); return this; } pure P opBinary(Op o)(T a) if (o=="*"||o=="/") { return mixin("P(x"~o~"a, y"~o~"a)"); } P opOpAssign(Op o)(T a) if (o=="*"||o=="/") { mixin("x"~o~"=a; y"~o~"=a;"); return this; } pure T opBinary(Op o: "*")(P r) { return x*r.x+y*r.y; } pure T hypot2() { return x^^2+y^^2; } } pure T distManhattan(T)(Point2!T p1, Point2!T p2) { return (p1.x-p2.x).abs + (p1.y-p2.y).abs; } pure T cross(T)(Point2!T p1, Point2!T p2) { return p1.x*p2.y - p1.y*p2.x; } struct Point3(T) { alias P = Point3!T, Op = string; T x, y, z; pure P opBinary(Op o)(P r) if (o=="+"||o=="-") { return mixin("P(x"~o~"r.x, y"~o~"r.y, z"~o~"r.z)"); } P opOpAssign(Op o)(P r) if (o=="+"||o=="-") { mixin("x"~o~"=r.x; y"~o~"=r.y; z"~o~"=r.z;"); return this; } pure P opBinary(Op o)(T a) if (o=="*"||o=="/") { return mixin("P(x"~o~"a, y"~o~"a, z"~o~"a)"); } P opOpAssign(Op o)(T a) if (o=="*"||o=="/") { mixin("x"~o~"=a; y"~o~"=a; z"~o~"=a;"); return this; } pure T opBinary(Op o: "*")(P r) { return x*r.x+y*r.y+z*r.z; } pure T hypot2() { return x^^2+y^^2+z^^2; } } pure Point3!T cross(T)(Point3!T p1, Point3!T p2) { return Point3!T(p1.y*p2.z - p1.z*p2.y, p1.z*p2.x - p1.x*p2.z, p1.x*p2.y - p1.y*p2.x); } auto io = IO!()(); import std.stdio; struct IO(string floatFormat = "%.10f", string delimiter = " ", alias IN = stdin, alias OUT = stdout) { import std.conv, std.format, std.meta, std.traits; alias assignable = hasAssignableElements; auto getV(T...)(ref T v) { foreach (ref w; v) get(w); } auto getA(T)(size_t n, ref T v) if (assignable!T) { v = new T(n); foreach (ref w; v) get(w); } auto getC(T...)(size_t n, ref T v) if (allSatisfy!(assignable, T)) { foreach (ref w; v) w = new typeof(w)(n); foreach (i; 0..n) foreach (ref w; v) get(w[i]); } auto getM(T)(size_t r, size_t c, ref T v) if (assignable!T && assignable!(ElementType!T)) { v = new T(r); foreach (ref w; v) getA(c, w); } template getS(E...) { auto getS(T)(size_t n, ref T v) { v = new T(n); foreach (ref w; v) foreach (e; E) mixin("get(w."~e~");"); } } auto put(bool flush = false, T...)(T v) { foreach (i, w; v) { putA(w); if (i < v.length-1) OUT.write(delimiter); } OUT.writeln; static if (flush) OUT.flush(); } auto putB(S, T)(bool c, S t, T f) { if (c) put(t); else put(f); } auto putRaw(T...)(T v) { OUT.write(v); OUT.writeln; } private { dchar[] buf; auto sp = (new dchar[](0)).splitter; void nextLine() { IN.readln(buf); sp = buf.splitter; } auto get(T)(ref T v) { if (sp.empty) nextLine(); v = sp.front.to!T; sp.popFront(); } auto putR(T)(T v) { auto w = v; while (!w.empty) { putA(w.front); w.popFront(); if (!w.empty) OUT.write(delimiter); } } auto putA(T)(T v) { static if (isInputRange!T && !isSomeString!T) putR(v); else if (isFloatingPoint!T) OUT.write(format(floatFormat, v)); else OUT.write(v); } } }