Submission #1135950


Source Code Expand

/+ dub.sdl:
    name "F"
    dependency "dcomp" version=">=0.6.0"
+/

import std.stdio, std.range, std.conv, std.algorithm;
import std.math;
// import dcomp.foundation;
// import dcomp.scanner;
// import dcomp.array;
// import dcomp.algorithm;

// import dcomp.twosat;
import core.bitop : bsr;

immutable INF = 10^^9 + 10^^7;

int n;
int[] pos;

//md より大きくは出来ない
bool solve(int md) {
    int[2][] v;
    foreach (int i, d; pos) {
        v ~= [d, i];
    }
    v = v.sort!((l, r) => cmp(l[], r[]) == -1).array;
    int m = v.length.to!int;
    int lg = m.bsr;
    if ((2^^lg) < m) lg++;
    m = 1<<lg;

    int getI(int i, int x) {
        return binSearch!(idx => cmp(v[idx][], [x, i].fixed[]) != -1)(-1, v.length.to!int);
    }

    auto sat = TwoSat(2*n + 2*m);
    foreach (i; 0..n) {
        // exactly 1 true
        sat.addCond(2*i, true, 2*i+1, true);
        sat.addCond(2*i, false, 2*i+1, false);
    }
    //make segtree
    foreach (i; 1..m) {
        sat.addCond(2*n+2*i, false, 2*n+i, true);
        sat.addCond(2*n+2*i+1, false, 2*n+i, true);
    }

    void query(int a, int b, int i, int l = 0, int r = m, int k = 1) {
        if (b <= l || r <= a) return;
        if (a <= l && r <= b) {
            sat.addCond(i, false, 2*n+k, false);
            return;
        }
        int md = (l+r)/2;
        query(a, b, i, l, md, 2*k);
        query(a, b, i, md, r, 2*k+1);
    }
    foreach (int i, x; pos) {
        int idx = getI(i, x);
        query(getI(-1, x-md), idx, i);
        query(idx+1, getI(INF, x+md), i);
        sat.addCond(i, false, 2*n + m + idx, true);
    }
    return sat.exec() == false;
}

int main() {
    auto sc = new Scanner(stdin);
    sc.read(n);
    pos = new int[2*n];
    pos.each!((ref x) => sc.read(x));
    writeln(binSearch!(md => solve(md))(-1, INF));
    return 0;
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/twosat.d */
// module dcomp.twosat;

// import dcomp.graph.scc;
// import dcomp.array;

struct TwoSat {
    bool[] res;

    struct Edge {int to;}
    import std.array;
//    Edge[][] g;
    FastAppender!(Edge[])[] g;

    // add ((a == aExp) || (b == bExp))
    void addCond(int a, bool aExp, int b, bool bExp) {
        void addEdge(int l, int r) {
            g[l] ~= Edge(r);
        }
        addEdge(2*a+(aExp?0:1), 2*b+(bExp?1:0));
        addEdge(2*b+(bExp?0:1), 2*a+(aExp?1:0));
    }
    bool exec() {
        import std.algorithm : map;
        import std.conv : to;
        int n = res.length.to!int;
        auto sccInfo = scc(g.map!(v => v.data).array);
        for (int i = 0; i < n; i++) {
            if (sccInfo.id[2*i] == sccInfo.id[2*i+1]) return false;
            res[i] = sccInfo.id[2*i] < sccInfo.id[2*i+1];
        }
        return true;
    }
    this(int n) {
        res = new bool[n];
        g = new FastAppender!(Edge[])[](2*n);
    }
}

unittest {
    import std.algorithm, std.conv, std.stdio, std.range;
    import std.random;
    import std.typecons;
    import std.datetime;

    struct E {int to;}

    writeln("TwoSat Random10000");
    void f() {
        int n = uniform(1, 50);
        int m = uniform(1, 100);
        auto ans = new bool[n];
        auto sat = TwoSat(n);
        ans.each!((ref x) => x = uniform(0, 2) == 1);
        struct N {int i; bool expect;}
        N[2][] conds;
        foreach (i; 0..m) {
            int x = uniform(0, n);
            int y = uniform(0, n);
            while (true) {
                bool f = uniform(0, 2) == 1;
                bool g = uniform(0, 2) == 1;
                if (ans[x] != f && ans[y] != g) continue;
                sat.addCond(x, f, y, g);
                conds ~= [N(x, f), N(y, g)];
                break;
            }
        }
        assert(sat.exec());
        auto res = sat.res;
        foreach (cond; conds) {
            int x = cond[0].i;
            bool f = cond[0].expect;
            int y = cond[1].i;
            bool g = cond[1].expect;
            assert(res[x] == f || res[y] == g);
        }
    }
    auto ti = benchmark!(f)(10000);
    writeln(ti[0].msecs, "ms");
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/graph/scc.d */
// module dcomp.graph.scc;

struct SCC {
    int[] id; // vertex id -> scc id
    int[][] groups; // scc id -> scc vertexs
    int count; // scc count
    this(int n) {
        id = new int[n];
    }
}

// import dcomp.array;

SCC scc(T)(T g) {
    import std.array : appender;
    import std.range;
    import std.algorithm : each, map;
    import std.conv : to;
    int n = g.length.to!int;
    //make reverse graph
    struct Edge {int to;}
    FastAppender!(Edge[])[] rg_buf = new FastAppender!(Edge[])[](n);
    g.each!((i, v) => v.each!(e => rg_buf[e.to] ~= Edge(i.to!int)));
    auto rg = rg_buf.map!(v => v.data).array;

    auto sccInfo = SCC(n);
    with (sccInfo) {
        auto used = new bool[n];

        //make backorder list
        auto vs = appender!(int[])();
        void dfs(int v) {
            used[v] = true;
            foreach (e; g[v]) {
                if (used[e.to]) continue;
                dfs(e.to);
            }
            vs ~= v;
        }
        foreach (i; 0..n) {
            if (used[i]) continue;
            dfs(i);
        }

        used[] = false;        
        count = 0;
        auto buf = appender!(int[])();
        void rdfs(int v) {
            used[v] = true;
            id[v] = count;
            buf ~= v;
            foreach (e; rg[v]) {
                if (used[e.to]) continue;
                rdfs(e.to);
            }
        }
        foreach_reverse (i; vs.data) {
            if (used[i]) continue;
            rdfs(i);
            groups ~= buf.data().dup;
            buf.clear();
            count++;
        }
    }
    return sccInfo;
}

unittest {
    import std.algorithm, std.conv, std.stdio, std.range;
    import std.random;
    import std.typecons;
    import std.datetime;

    struct E {int to;}

    writeln("SCC Random1000");
    void f() {
        int n = uniform(1, 50);
        int p = uniform(1, 50);
        E[][] g = new E[][n];
        bool[][] naive = new bool[][](n, n);
        foreach (i; 0..n) {
            foreach (j; 0..n) {
                if (i == j) continue;
                if (uniform(0, 100) < p) {
                    g[i] ~= E(j);
                    naive[i][j] = true;
                }
            }
        }

        auto sccInfo = scc(g);

        foreach (k; 0..n) {
            foreach (i; 0..n) {
                foreach (j; 0..n) {
                    naive[i][j] |= naive[i][k] && naive[k][j];
                }
            }
        }

        foreach (i; 0..n) {
            foreach (j; i+1..n) {
                bool same = sccInfo.id[i] == sccInfo.id[j];
                if (same) {
                    assert(naive[i][j] && naive[j][i]);
                } else {
                    assert(!naive[i][j] || !naive[j][i]);                    
                    if (sccInfo.id[i] < sccInfo.id[j]) {
                        assert(!naive[j][i]);
                    } else {
                        assert(!naive[i][j]);
                    }
                }
            }
        }
    }
    auto ti = benchmark!(f)(1000);
    writeln(ti[0].msecs, "ms");
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/algorithm.d */
// module dcomp.algorithm;

import std.range.primitives;
import std.traits : isFloatingPoint, isIntegral;

//[0,0,0,...,1,1,1]で、初めて1となる場所を探す。pred(l) == 0, pred(r) == 1と仮定
T binSearch(alias pred, T)(T l, T r) if (isIntegral!T) {
    while (r-l > 1) {
        T md = (l+r)/2;
        if (!pred(md)) l = md;
        else r = md;
    }
    return r;
}

T binSearch(alias pred, T)(T l, T r, int cnt = 60) if (isFloatingPoint!T) {
    foreach (i; 0..cnt) {
        T md = (l+r)/2;
        if (!pred(md)) l = md;
        else r = md;
    }
    return r;
}

Rotator!Range rotator(Range)(Range r) {
    return Rotator!Range(r);
}

struct Rotator(Range)
if (isForwardRange!Range && hasLength!Range) {
    size_t cnt;
    Range start, now;
    this(Range r) {
        cnt = 0;
        start = r.save;
        now = r.save;
    }
    this(this) {
        start = start.save;
        now = now.save;
    }
    @property bool empty() {
        return now.empty;
    }
    @property auto front() {
        assert(!now.empty);
        import std.range : take, chain;
        return chain(now, start.take(cnt));
    }
    @property Rotator!Range save() {
        return this;
    }
    void popFront() {
        cnt++;
        now.popFront;
    }
}


E minimum(alias pred = "a < b", Range, E = ElementType!Range)(Range range, E seed)
if (isInputRange!Range && !isInfinite!Range) {
    import std.algorithm, std.functional;
    return reduce!((a, b) => binaryFun!pred(a, b) ? a : b)(seed, range);
}

ElementType!Range minimum(alias pred = "a < b", Range)(Range range) {
    assert(!range.empty, "range must not empty");
    auto e = range.front; range.popFront;
    return minimum!pred(range, e);
}

E maximum(alias pred = "a < b", Range, E = ElementType!Range)(Range range, E seed)
if (isInputRange!Range && !isInfinite!Range) {
    import std.algorithm, std.functional;
    return reduce!((a, b) => binaryFun!pred(a, b) ? b : a)(seed, range);
}

ElementType!Range maximum(alias pred = "a < b", Range)(Range range) {
    assert(!range.empty, "range must not empty");
    auto e = range.front; range.popFront;
    return maximum!pred(range, e);
}

unittest {
    assert(minimum([2, 1, 3]) == 1);
    assert(minimum!"a > b"([2, 1, 3]) == 3);
    assert(minimum([2, 1, 3], -1) == -1);
    assert(minimum!"a > b"([2, 1, 3], 100) == 100);

    assert(maximum([2, 1, 3]) == 3);
    assert(maximum!"a > b"([2, 1, 3]) == 1);
    assert(maximum([2, 1, 3], 100) == 100);
    assert(maximum!"a > b"([2, 1, 3], -1) == -1);
}

bool[ElementType!Range] toMap(Range)(Range r) {
    import std.algorithm : each;
    bool[ElementType!Range] res;
    r.each!(a => res[a] = true);
    return res;
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/scanner.d */
// module dcomp.scanner;

class Scanner {
    import std.stdio : File;
    import std.conv : to;
    import std.range : front, popFront, array, ElementType;
    import std.array : split;
    import std.traits : isSomeChar, isStaticArray, isArray; 
    import std.algorithm : map;
    File f;
    this(File f) {
        this.f = f;
    }
    string[] buf;
    private bool succ() {
        while (!buf.length) {
            if (f.eof) return false;
            buf = f.readln.split;
        }
        return true;
    }
    private bool readSingle(T)(ref T x) {
        if (!succ()) return false;
        static if (isArray!T) {
            alias E = ElementType!T;
            static if (isSomeChar!E) {
                //string or char[10] etc
                x = buf.front;
                buf.popFront;
            } else {
                static if (isStaticArray!T) {
                    //static
                    assert(buf.length == T.length);
                }
                x = buf.map!(to!E).array;
                buf.length = 0;                
            }
        } else {
            x = buf.front.to!T;
            buf.popFront;            
        }
        return true;
    }
    int read(T, Args...)(ref T x, auto ref Args args) {
        if (!readSingle(x)) return 0;
        static if (args.length == 0) {
            return 1;
        } else {
            return 1 + read(args);
        }
    }
}

unittest {
    import std.path : buildPath;
    import std.file : tempDir;
    import std.algorithm : equal;
    import std.stdio : File;
    string fileName = buildPath(tempDir, "kyuridenanmaida.txt");
    auto fout = File(fileName, "w");
    fout.writeln("1 2 3");
    fout.writeln("ab cde");
    fout.writeln("1.0 1.0 2.0");
    fout.close;
    Scanner sc = new Scanner(File(fileName, "r"));
    int a;
    int[2] b;
    char[2] c;
    string d;
    double e;
    double[] f;
    sc.read(a, b, c, d, e, f);
    assert(a == 1);
    assert(equal(b[], [2, 3]));
    assert(equal(c[], "ab"));
    assert(equal(d, "cde"));
    assert(e == 1.0);
    assert(equal(f, [1.0, 2.0]));
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/foundation.d */
// module dcomp.foundation;
//fold(for old compiler)
static if (__VERSION__ <= 2070) {
    template fold(fun...) if (fun.length >= 1) {
        auto fold(R, S...)(R r, S seed) {
            import std.algorithm : reduce;
            static if (S.length < 2) {
                return reduce!fun(seed, r);
            } else {
                import std.typecons : tuple;
                return reduce!fun(tuple(seed), r);
            }
        }
    }
    unittest {
        import std.stdio;
        auto l = [1, 2, 3, 4, 5];
        assert(l.fold!"a+b"(10) == 25);
    }
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/array.d */
// module dcomp.array;

T[N] fixed(T, int N)(T[N] a) {return a;}

//this is not reference type!(please attention to copy)
struct FastAppender(A) {
    import std.algorithm : max;
    import std.range.primitives : ElementEncodingType;
    import core.stdc.string : memcpy;

    private alias T = ElementEncodingType!A;
    private T* _data;
    private size_t len, cap;

    void reserve(size_t nlen) {
        import core.memory : GC;
        if (nlen <= cap) return;
        
        void* nx = GC.malloc(nlen * T.sizeof);            

        cap = nlen;
        if (len) memcpy(nx, _data, len * T.sizeof);
        _data = cast(T*)(nx);
    }
    void opOpAssign(string op : "~")(T item) {
        if (len == cap) {
            reserve(max(4, cap*2));
        }
        _data[len++] = item;
    }
    void clear() {
        len = 0;
    }    
    T[] data() {
        return (_data) ? _data[0..len] : null;
    }
}

unittest {
    import std.stdio, std.algorithm;
    auto u = FastAppender!(int[])();
    u ~= 4; u ~= 5;
    assert(equal(u.data, [4, 5]));
}

Submission Info

Submission Time
Task F - Flags
User yosupo
Language D (LDC 0.17.0)
Score 1200
Code Size 14440 Byte
Status AC
Exec Time 3198 ms
Memory 141132 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 1200 / 1200
Status
AC × 3
AC × 30
Set Name Test Cases
Sample 00_example_01.txt, 00_example_02.txt, 00_example_03.txt
All 00_example_01.txt, 00_example_02.txt, 00_example_03.txt, 01.txt, 02.txt, 03.txt, 04.txt, 05.txt, 06.txt, 07.txt, 08.txt, 09.txt, 10.txt, 11.txt, 12.txt, 13.txt, 14.txt, 15.txt, 16.txt, 17.txt, 18.txt, 19.txt, 20.txt, 21.txt, 22.txt, 23.txt, 24.txt, 25.txt, 26.txt, 27.txt
Case Name Status Exec Time Memory
00_example_01.txt AC 2 ms 508 KB
00_example_02.txt AC 2 ms 764 KB
00_example_03.txt AC 5 ms 4092 KB
01.txt AC 64 ms 9980 KB
02.txt AC 28 ms 3708 KB
03.txt AC 9 ms 3324 KB
04.txt AC 13 ms 4860 KB
05.txt AC 14 ms 3452 KB
06.txt AC 2498 ms 84476 KB
07.txt AC 2354 ms 92668 KB
08.txt AC 2499 ms 92716 KB
09.txt AC 64 ms 4604 KB
10.txt AC 27 ms 3708 KB
11.txt AC 9 ms 3964 KB
12.txt AC 12 ms 3452 KB
13.txt AC 14 ms 4860 KB
14.txt AC 2318 ms 75900 KB
15.txt AC 2314 ms 76668 KB
16.txt AC 2412 ms 75260 KB
17.txt AC 64 ms 8444 KB
18.txt AC 29 ms 4476 KB
19.txt AC 2427 ms 83708 KB
20.txt AC 2692 ms 89236 KB
21.txt AC 2933 ms 107264 KB
22.txt AC 3171 ms 141132 KB
23.txt AC 3198 ms 108352 KB
24.txt AC 2612 ms 129360 KB
25.txt AC 2590 ms 106172 KB
26.txt AC 2714 ms 92728 KB
27.txt AC 1 ms 380 KB