Submission #2082895


Source Code Expand

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.Reader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        MyInput in = new MyInput(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskE {
        public void solve(int testNumber, MyInput in, PrintWriter out) {
            int n = in.nextInt();
            int[] d = in.nextIntArray(n);
//        int m = (int)Math.sqrt(n);
//        Bucket[] bucket = new Bucket[n];
//        for (int i = 0; i < n; i++) {
//            ;
//        }
            SplayTreeIndex tree = new SplayTreeIndex();
            for (int i = 0; i < n; i++) {
                tree.insert(i, d[n - 1 - i]);
            }
            int cnt = 0;
            for (int i = 0; i < n; i++) {
//            for (int j = 0; j < n - i; j++) {
//                dump("dump1", i, j, tree.find(j).value);
//            }

                SplayTreeIndex.Node node = tree.find(0);
//            dump(i, cnt, node.value);
                if (node.value < 0) {
                    cnt++;
                    int idx = SplayTreeIndex.getCount(node.left);
                    tree.add(idx, idx, 1);
                    node = tree.find(0);
                }
                if (node.value < 0 || cnt >= 2) {
                    cnt = 2;
                    break;
                }
                if (i == n - 1) break;

                tree.add(0, node.value, -1);
                tree.remove(0);
                if (node.value == -1 || node.value == n - 2 - i) continue;
//            for (int j = 0; j < n - i - 1; j++) {
//                dump(i, j, tree.find(j).value);
//            }

                int val1 = tree.find(node.value).value;
                int val2 = tree.find(node.value + 1).value;
//            dump(n, i, SplayTreeIndex.getCount(tree.root), node.value, val1, val2);
                if (val1 < val2) {
//                for (int j = 0; j < n - i - 1; j++) {
//                    dump(i, j, tree.find(j).value);
//                }
                    int l = tree.findLeft(val1);
//                for (int j = 0; j < n - i - 1; j++) {
//                    dump(i, j, tree.find(j).value);
//                }
//                dump("findRight", val2);
                    int r = tree.findRight(val2);
//                for (int j = 0; j < n - i - 1; j++) {
//                    dump(i, j, tree.find(j).value);
//                }
                    // revolve [l,l+1,l+2,...,r] -> [r-t+1,r-t+2,..,r,l,l+1,...,r-t]
                    tree.revolve(l, r, r - node.value);
//                dump("revolve", l, r, r - (node.value));
                }
            }
//        dump(cnt);
            out.println(cnt == 0 ? "YES" : cnt == 1 ? "NO" : "ABSOLUTELY NO");
        }

    }

    static class SplayTreeIndex {
        SplayTreeIndex.Node root;
        final SplayTreeIndex.Node[] sep = new SplayTreeIndex.Node[3];

        int findLeft(int val) {
            SplayTreeIndex.Node cur = root;
            while (true) {
                cur.pushDown();
//            dump("1", cur.value);
                if (cur.left == null) {
                    if (cur.value == val) break;
                    cur = cur.right;
                    continue;
                }

                int minL = cur.left.pushDown().min;
                int maxL = cur.left.pushDown().max;
                if (minL <= val && val <= maxL) {
                    cur = cur.left;
//                dump("3");
                } else {
                    if (cur.value == val) break;
                    cur = cur.right;
//                dump("4");
                }
            }
            root = cur.splay();
            return getCount(cur.left);
        }

        int findRight(int val) {
            SplayTreeIndex.Node cur = root;
            while (true) {
                cur.pushDown();
                if (cur.right == null) {
                    if (cur.value == val) break;
                    cur = cur.left;
                    continue;
                }

                int min = cur.right.pushDown().min;
                int max = cur.right.pushDown().max;
                if (min <= val && val <= max) {
                    cur = cur.right;
                } else {
                    if (cur.value == val) break;
                    cur = cur.left;
                }
            }
            root = cur.splay();
            return getCount(cur.left);
        }

        static int getCount(SplayTreeIndex.Node n) {
            return n == null ? 0 : n.count;
        }

        static SplayTreeIndex.Node getLeft(SplayTreeIndex.Node n) {
            return n == null ? null : n.getLeft();
        }

        static SplayTreeIndex.Node getRight(SplayTreeIndex.Node n) {
            return n == null ? null : n.getRight();
        }

        void insert(int index, int value) {
            insert(index, new SplayTreeIndex.Node(value, null));
        }

        void insert(int index, SplayTreeIndex.Node insertNode) {
            if (root == null) {
                root = insertNode;
                return;
            }
            final int n = getCount(root);
            if (n < index) throw new RuntimeException();
            final SplayTreeIndex.Node add = insertNode;
            if (n == index) {
                SplayTreeIndex.Node node = find(n - 1);
                SplayTreeIndex.Node.linkRight(add, node);
            } else {
                final SplayTreeIndex.Node node = find(index);
                final SplayTreeIndex.Node nl = SplayTreeIndex.Node.cut(node.getLeft());
                SplayTreeIndex.Node.linkLeft(nl, add);
                SplayTreeIndex.Node.linkRight(node, add);
            }
            root = add.splay();
        }

        SplayTreeIndex.Node find(SplayTreeIndex.Node node, int index) {
            while (node != null) {
                node.pushDown();
                if (getCount(node.getLeft()) > index) {
                    node = node.getLeft();
                } else if (getCount(node.getLeft()) == index) {
                    return root = node.splay();
                } else {
                    index -= getCount(node.getLeft()) + 1;
                    node = node.getRight();
                }
            }
            return null;
        }

        SplayTreeIndex.Node find(int index) {
            return find(root, index);
        }

        void remove(final int index) {
            if (index < 0 || getCount(root) <= index) {
                throw new RuntimeException();
            }

            final SplayTreeIndex.Node node = find(index);
            final SplayTreeIndex.Node nl = SplayTreeIndex.Node.cut(node.getLeft());
            final SplayTreeIndex.Node nr = SplayTreeIndex.Node.cut(node.getRight());

            root = SplayTreeIndex.Node.merge(nl, nr);
        }

        SplayTreeIndex.Node[] separate(int l, int r) {
            final SplayTreeIndex.Node left = SplayTreeIndex.Node.cut(getLeft(find(l)));
            final SplayTreeIndex.Node mid = find(r - l);
            final SplayTreeIndex.Node right = SplayTreeIndex.Node.cut(getRight(mid));

            sep[0] = left;
            sep[1] = mid;
            sep[2] = right;

            return sep;
        }

        void revolve(int l, int r, int t) {
            rotate(l, r, t % (r - l + 1));
        }

        void rotate(int l, int r, int t) {
            if (r - l < t) while (true) ;
            SplayTreeIndex.Node[] sep = separate(l, r);

            SplayTreeIndex.Node n = find(sep[1], r - l - t);
            SplayTreeIndex.Node nr = SplayTreeIndex.Node.cut(getRight(n));
            root = SplayTreeIndex.Node.merge(SplayTreeIndex.Node.merge(sep[0], nr), SplayTreeIndex.Node.merge(n, sep[2]));
        }

        void add(int l, int r, int val) {
            SplayTreeIndex.Node[] sep = separate(l, r);
            sep[1].addSubTree(val);
            root = SplayTreeIndex.Node.merge(SplayTreeIndex.Node.merge(sep[0], sep[1]), sep[2]);
        }

        static class Node {
            int value;
            int sum;
            int min;
            int max;
            int count;
            int dval;
            boolean reverse;
            boolean needPushDown;
            SplayTreeIndex.Node left;
            SplayTreeIndex.Node right;
            SplayTreeIndex.Node parent;

            void update() {
                count = 1;
                min = max = sum = value;
                if (getLeft() != null) {
                    count += left.count;
                    sum += left.sum;
                    min = Math.min(min, left.min);
                    max = Math.max(max, left.max);
                }
                if (getRight() != null) {
                    count += right.count;
                    sum += right.sum;
                    min = Math.min(min, right.min);
                    max = Math.max(max, right.max);
                }
                sum += count * dval;
                min += dval;
                max += dval;
            }

            void addSubTree(int val) {
                dval += val;
                sum += val * count;
                needPushDown = true;
            }

            static void receiveLazyValue(SplayTreeIndex.Node n) {
                if (n != null) {
                    n.dval += n.parent.dval;
                    n.reverse ^= n.parent.reverse;
                    n.min += n.parent.dval;
                    n.max += n.parent.dval;
                    n.sum += n.parent.dval * n.count;
                    n.needPushDown = true;
                }
            }

            SplayTreeIndex.Node pushDown() {
                if (needPushDown) {
                    receiveLazyValue(left);
                    receiveLazyValue(right);
                    value += dval;
                    dval = 0;
                    if (reverse) {
                        final SplayTreeIndex.Node n = left;
                        left = right;
                        right = n;
                        reverse = false;
                    }
                    needPushDown = false;
                }
                return this;
            }

            SplayTreeIndex.Node getLeft() {
                pushDown();
                return left;
            }

            SplayTreeIndex.Node getRight() {
                pushDown();
                return right;
            }

            static SplayTreeIndex.Node merge(final SplayTreeIndex.Node nl, final SplayTreeIndex.Node nr) {
                if (nl == null) return nr;
                if (nr == null) return nl;
                nl.splay();
                nr.splay();
                final SplayTreeIndex.Node leftMaxNode = nl.maxNode();
                SplayTreeIndex.Node.linkRight(nr, leftMaxNode);
                return leftMaxNode;
            }

            static void linkLeft(final SplayTreeIndex.Node n, final SplayTreeIndex.Node p) {
                if (p != null) {
                    p.pushDown();
                    cut(p.getLeft());
                    p.left = n;
                }
                if (n != null) {
                    n.parent = p;
                }
                if (p != null) {
                    p.update();
                }
            }

            static void linkRight(final SplayTreeIndex.Node n, final SplayTreeIndex.Node p) {
                if (p != null) {
                    p.pushDown();
                    cut(p.getRight());
                    p.right = n;
                }
                if (n != null) {
                    n.parent = p;
                }
                if (p != null) {
                    p.update();
                }
            }

            static SplayTreeIndex.Node cut(final SplayTreeIndex.Node n) {
                if (n == null || n.parent == null) {
                    return n;
                }
                n.parent.pushDown();
                if (n.parent.left == n) {
                    n.parent.left = null;
                } else {
                    n.parent.right = null;
                }
                n.parent.update();
                n.parent = null;
                return n;
            }

            public Node(int value, SplayTreeIndex.Node parent) {
                this.value = value;
                this.parent = parent;
                update();
            }

            void rotateRight() {
                final SplayTreeIndex.Node x = this;
                final SplayTreeIndex.Node p = x.parent;
                final SplayTreeIndex.Node g = p.parent;
//			if(g != null) g.pushDown();
                p.pushDown();
                x.pushDown();
                p.left = x.right;
                if (x.right != null) {
                    x.right.parent = p;
                }
                p.parent = x;
                x.right = p;
                x.parent = g;
                p.update();
                x.update();
                if (g != null) {
                    if (g.left == p) g.left = x;
                    else if (g.right == p) g.right = x;
//				g.update();
                }
            }

            void rotateLeft() {
                final SplayTreeIndex.Node x = this;
                final SplayTreeIndex.Node p = x.parent;
                final SplayTreeIndex.Node g = p.parent;
//			if(g != null) g.pushDown();
                p.pushDown();
                x.pushDown();
                p.right = x.left;
                if (x.left != null) {
                    x.left.parent = p;
                }
                p.parent = x;
                x.left = p;
                x.parent = g;
                p.update();
                x.update();
                if (g != null) {
                    if (g.left == p) g.left = x;
                    else if (g.right == p) g.right = x;
//				g.update();
                }
            }

            public SplayTreeIndex.Node splay() {
                final SplayTreeIndex.Node x = this;
                while (x.parent != null) {
                    final SplayTreeIndex.Node p = x.parent;
                    if (p.parent == null) {
                        // zig step
                        if (p.getLeft() == x) {
                            x.rotateRight();
                        } else {
                            x.rotateLeft();
                        }
                    } else {
                        final SplayTreeIndex.Node g = p.parent;
                        // zig-zig step / zig-zag step
                        if (g.getLeft() == p) {
                            if (p.getLeft() == x) {
                                p.rotateRight();
                                x.rotateRight();
                            } else {
                                x.rotateLeft();
                                x.rotateRight();
                            }
                        } else {
                            if (p.getLeft() == x) {
                                x.rotateRight();
                                x.rotateLeft();
                            } else {
                                p.rotateLeft();
                                x.rotateLeft();
                            }
                        }
                    }
                }
                return x;
            }

            SplayTreeIndex.Node maxNode() {
                SplayTreeIndex.Node n = this;
                while (true) {
                    n.pushDown();
                    if (n.right == null) break;
                    n = n.right;
                }
                return n.splay();
            }

        }

    }

    static class MyInput {
        private final BufferedReader in;
        private static int pos;
        private static int readLen;
        private static final char[] buffer = new char[1024 * 8];
        private static char[] str = new char[500 * 8 * 2];
        private static boolean[] isDigit = new boolean[256];
        private static boolean[] isSpace = new boolean[256];
        private static boolean[] isLineSep = new boolean[256];

        static {
            for (int i = 0; i < 10; i++) {
                isDigit['0' + i] = true;
            }
            isDigit['-'] = true;
            isSpace[' '] = isSpace['\r'] = isSpace['\n'] = isSpace['\t'] = true;
            isLineSep['\r'] = isLineSep['\n'] = true;
        }

        public MyInput(InputStream is) {
            in = new BufferedReader(new InputStreamReader(is));
        }

        public int read() {
            if (pos >= readLen) {
                pos = 0;
                try {
                    readLen = in.read(buffer);
                } catch (IOException e) {
                    throw new RuntimeException();
                }
                if (readLen <= 0) {
                    throw new MyInput.EndOfFileRuntimeException();
                }
            }
            return buffer[pos++];
        }

        public int nextInt() {
            int len = 0;
            str[len++] = nextChar();
            len = reads(len, isSpace);
            int i = 0;
            int ret = 0;
            if (str[0] == '-') {
                i = 1;
            }
            for (; i < len; i++) ret = ret * 10 + str[i] - '0';
            if (str[0] == '-') {
                ret = -ret;
            }
            return ret;
        }

        public char nextChar() {
            while (true) {
                final int c = read();
                if (!isSpace[c]) {
                    return (char) c;
                }
            }
        }

        int reads(int len, boolean[] accept) {
            try {
                while (true) {
                    final int c = read();
                    if (accept[c]) {
                        break;
                    }
                    if (str.length == len) {
                        char[] rep = new char[str.length * 3 / 2];
                        System.arraycopy(str, 0, rep, 0, str.length);
                        str = rep;
                    }
                    str[len++] = (char) c;
                }
            } catch (MyInput.EndOfFileRuntimeException e) {
            }
            return len;
        }

        public int[] nextIntArray(final int n) {
            final int[] res = new int[n];
            for (int i = 0; i < n; i++) {
                res[i] = nextInt();
            }
            return res;
        }

        static class EndOfFileRuntimeException extends RuntimeException {
        }

    }
}

Submission Info

Submission Time
Task E - グラフの問題
User tanzaku
Language Java8 (OpenJDK 1.8.0)
Score 1000
Code Size 19574 Byte
Status AC
Exec Time 792 ms
Memory 36428 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 1000 / 1000
Status
AC × 3
AC × 79
Set Name Test Cases
Sample s1.txt, s2.txt, s3.txt
All 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, 28.txt, 29.txt, 30.txt, 31.txt, 32.txt, 33.txt, 34.txt, 35.txt, 36.txt, 37.txt, 38.txt, 39.txt, 40.txt, 41.txt, 42.txt, 43.txt, 44.txt, 45.txt, 46.txt, 47.txt, 48.txt, 49.txt, 50.txt, 51.txt, 52.txt, 53.txt, 54.txt, 55.txt, 56.txt, 57.txt, 58.txt, 59.txt, 60.txt, 61.txt, 62.txt, 63.txt, 64.txt, 65.txt, 66.txt, 67.txt, 68.txt, 69.txt, 70.txt, 71.txt, 72.txt, 73.txt, 74.txt, 75.txt, 76.txt, s1.txt, s2.txt, s3.txt
Case Name Status Exec Time Memory
01.txt AC 445 ms 34784 KB
02.txt AC 555 ms 31520 KB
03.txt AC 617 ms 32436 KB
04.txt AC 524 ms 32340 KB
05.txt AC 433 ms 30228 KB
06.txt AC 506 ms 30212 KB
07.txt AC 402 ms 33284 KB
08.txt AC 424 ms 31100 KB
09.txt AC 407 ms 30128 KB
10.txt AC 646 ms 33960 KB
11.txt AC 626 ms 35492 KB
12.txt AC 671 ms 32164 KB
13.txt AC 378 ms 34768 KB
14.txt AC 346 ms 32964 KB
15.txt AC 539 ms 32716 KB
16.txt AC 620 ms 29216 KB
17.txt AC 615 ms 30928 KB
18.txt AC 336 ms 28868 KB
19.txt AC 547 ms 32904 KB
20.txt AC 544 ms 34048 KB
21.txt AC 631 ms 32360 KB
22.txt AC 607 ms 34108 KB
23.txt AC 588 ms 31232 KB
24.txt AC 762 ms 31844 KB
25.txt AC 439 ms 29528 KB
26.txt AC 377 ms 31732 KB
27.txt AC 636 ms 31516 KB
28.txt AC 642 ms 31416 KB
29.txt AC 398 ms 32212 KB
30.txt AC 632 ms 34684 KB
31.txt AC 685 ms 32996 KB
32.txt AC 613 ms 32672 KB
33.txt AC 529 ms 30060 KB
34.txt AC 564 ms 31132 KB
35.txt AC 522 ms 30792 KB
36.txt AC 387 ms 32624 KB
37.txt AC 451 ms 30740 KB
38.txt AC 432 ms 33160 KB
39.txt AC 218 ms 29492 KB
40.txt AC 236 ms 28712 KB
41.txt AC 398 ms 30384 KB
42.txt AC 329 ms 31468 KB
43.txt AC 310 ms 30904 KB
44.txt AC 288 ms 30096 KB
45.txt AC 394 ms 33688 KB
46.txt AC 391 ms 33784 KB
47.txt AC 306 ms 32164 KB
48.txt AC 196 ms 29308 KB
49.txt AC 258 ms 31752 KB
50.txt AC 412 ms 29008 KB
51.txt AC 309 ms 30000 KB
52.txt AC 250 ms 29912 KB
53.txt AC 379 ms 31652 KB
54.txt AC 375 ms 30744 KB
55.txt AC 385 ms 30892 KB
56.txt AC 382 ms 33568 KB
57.txt AC 266 ms 30688 KB
58.txt AC 261 ms 31968 KB
59.txt AC 560 ms 36428 KB
60.txt AC 684 ms 33244 KB
61.txt AC 652 ms 34360 KB
62.txt AC 463 ms 33096 KB
63.txt AC 596 ms 33372 KB
64.txt AC 390 ms 33588 KB
65.txt AC 419 ms 34428 KB
66.txt AC 536 ms 32128 KB
67.txt AC 648 ms 32144 KB
68.txt AC 383 ms 31112 KB
69.txt AC 677 ms 34444 KB
70.txt AC 792 ms 32848 KB
71.txt AC 71 ms 18772 KB
72.txt AC 71 ms 18772 KB
73.txt AC 70 ms 18260 KB
74.txt AC 71 ms 18772 KB
75.txt AC 70 ms 21332 KB
76.txt AC 71 ms 18772 KB
s1.txt AC 71 ms 21460 KB
s2.txt AC 70 ms 19668 KB
s3.txt AC 73 ms 21076 KB