제출 #255294

#제출 시각아이디문제언어결과실행 시간메모리
255294model_codeProgression (NOI20_progression)Java
83 / 100
5150 ms208864 KiB
import java.io.*;
import java.util.*;
import java.lang.Math.*;

public class Progression {
    static long[] D;
    static long[] B;

    static class qval {
        public int len, prefix_len, suffix_len, subarray_len;
        public long sum, prefix_val, suffix_val, subarray_val;
        public qval() {}
        public void init(long val) {
            len = 1; sum = val;
            subarray_len = 0;
            subarray_val = 0;
            prefix_len = suffix_len = 1;
            prefix_val = suffix_val = val;
        }
        public void add(long val) {
            prefix_val += val;
            suffix_val += val;
            subarray_val += val;
            sum += val * len;
        }
        public void set(long val) {
            prefix_val = suffix_val = subarray_val = val;
            prefix_len = suffix_len = len;
            subarray_len = Math.max(0, len - 2);
            sum = val * len;
        }
    }

    static class SegmentTree {
        private qval[] V;
        private boolean[] lset;
        private long[] lazy_set;
        private long[] lazy_add;
        SegmentTree() {
            lazy_set = new long[1500010];
            lazy_add = new long[1500010];
            lset = new boolean[1500010];
            V = new qval[1500010];
        }
        public void build(int node, int S, int E) {
            V[node] = new qval();
            if (S == E) {
                V[node].init(B[S]);
                return;
            }
            int M = S + (E - S) / 2;
            build(node << 1, S, M);
            build(node << 1 | 1, M + 1, E);
            combine(V[node], V[node << 1], V[node << 1 | 1]);
        }
        private void combine(qval ret, qval left, qval right) {
            ret.len = left.len + right.len;
            ret.sum = left.sum + right.sum;

            ret.prefix_len = left.prefix_len;
            ret.prefix_val = left.prefix_val;
            if (left.prefix_len == left.len && left.prefix_val == right.prefix_val) {
                ret.prefix_len = left.len + right.prefix_len;
                ret.prefix_val = left.prefix_val;
            }

            ret.suffix_len = right.suffix_len;
            ret.suffix_val = right.suffix_val;
            if (right.suffix_len == right.len && left.suffix_val == right.suffix_val) {
                ret.suffix_len = right.len + left.suffix_len;
                ret.suffix_val = right.suffix_val;
            }

            if (left.subarray_len > right.subarray_len) {
                ret.subarray_len = left.subarray_len;
                ret.subarray_val = left.subarray_val;
            } else {
                ret.subarray_len = right.subarray_len;
                ret.subarray_val = right.subarray_val;
            }
            if (Math.min(left.len - 1, left.suffix_len) > ret.subarray_len) {
                ret.subarray_len = Math.min(left.len - 1, left.suffix_len);
                ret.subarray_val = left.suffix_val;
            }
            if (Math.min(right.len - 1, right.prefix_len) > ret.subarray_len) {
                ret.subarray_len = Math.min(right.len - 1, right.prefix_len);
                ret.subarray_val = right.prefix_val;
            }
            if (left.suffix_val == right.prefix_val &&
                Math.min(left.len - 1, left.suffix_len) +
                Math.min(right.len - 1, right.prefix_len) > ret.subarray_len) {
                ret.subarray_len = Math.min(left.len - 1, left.suffix_len) +
                    Math.min(right.len - 1, right.prefix_len);
                ret.subarray_val = left.suffix_val;
            }
        }
        private void push(int node) {
            if (lset[node]) {
                rset(node << 1, lazy_set[node]);
                rset(node << 1 | 1, lazy_set[node]);
                lset[node] = false;
                lazy_set[node] = 0;
            }
            if (lazy_add[node] != 0) {
                radd(node << 1, lazy_add[node]);
                radd(node << 1 | 1, lazy_add[node]);
                lazy_add[node] = 0;
            }
        }
        public void radd(int node, long QV) {
            if (lset[node]) V[node].set(lazy_set[node] += QV);
            else {
                lazy_add[node] += QV;
                V[node].add(QV);
            }
        }
        public void rset(int node, long QV) {
            lset[node] = true;
            lazy_add[node] = 0;
            V[node].set(lazy_set[node] = QV);
        }
        public qval query(int node, int S, int E, int QS, int QE) {
            if (QS <= S && E <= QE) return V[node];
            push(node);
            int M = S + (E - S) / 2;
            if (QE <= M) return query(node << 1, S, M, QS, QE);
            if (QS > M) return query(node << 1 | 1, M + 1, E, QS, QE);
            qval ret = new qval();
            combine(ret, query(node << 1, S, M, QS, M), query(node << 1 | 1, M + 1, E, M + 1, QE));
            return ret;
        }
        public void add(int node, int S, int E, int QS, int QE, long QV) {
            if (QS <= S && E <= QE) {
                radd(node, QV);
                return;
            }
            push(node);
            int M = S + (E - S) / 2;
            if (QE <= M) add(node << 1, S, M, QS, QE, QV);
            else if (QS > M) add(node << 1 | 1, M + 1, E, QS, QE, QV);
            else {
                add(node << 1, S, M, QS, M, QV);
                add(node << 1 | 1, M + 1, E, M + 1, QE, QV);
            }
            combine(V[node], V[node << 1], V[node << 1 | 1]);
        }
        public void set(int node, int S, int E, int QS, int QE, long QV) {
            if (QS <= S && E <= QE) {
                rset(node, QV);
                return;
            }
            push(node);
            int M = S + (E - S) / 2;
            if (QE <= M) set(node << 1, S, M, QS, QE, QV);
            else if (QS > M) set(node << 1 | 1, M + 1, E, QS, QE, QV);
            else {
                set(node << 1, S, M, QS, M, QV);
                set(node << 1 | 1, M + 1, E, M + 1, QE, QV);
            }
            combine(V[node], V[node << 1], V[node << 1 | 1]);
        }
    }

    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;
        public Reader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }
        public int nextInt() throws IOException {
            int ret = 0;
            Boolean flip = false;
            byte c = read();
            while (c < '0' || c > '9') {
                if (c == '-') flip = true;
                c = read();
            }
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            return flip ? -ret : ret;
        }

        private void fillBuffer() throws IOException
        {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) {
                buffer[0] = -1;
            }
        }

        private byte read() throws IOException
        {
            if (bufferPointer == bytesRead) {
                fillBuffer();
            }
            return buffer[bufferPointer++];
        }
    }

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
        int N = reader.nextInt();
        int Q = reader.nextInt();
        D = new long[300010];
        B = new long[300010];
        for (int a = 1; a <= N; ++a) {
            D[a] = reader.nextInt();
            B[a] = D[a] - D[a - 1];
        }
        SegmentTree root = new SegmentTree();
        root.build(1, 1, N);
        while (Q-- > 0) {
            int op = reader.nextInt();
            if (op == 1) {
                int L, R; long S, C;
                L = reader.nextInt(); R = reader.nextInt();
                S = reader.nextInt(); C = reader.nextInt();
                root.add(1, 1, N, L, L, S);
                if (L != R) root.add(1, 1, N, L + 1, R, C);
                if (R != N) root.add(1, 1, N, R + 1, R + 1, -(S + (R - L) * C));
            } else if (op == 2) {
                int L, R; long S, C;
                L = reader.nextInt(); R = reader.nextInt();
                S = reader.nextInt(); C = reader.nextInt();
                long old_sum = root.query(1, 1, N, L, R).sum;
                long prefix = (L == 1 ? 0 : root.query(1, 1, N, 1, L - 1).sum);
                root.set(1, 1, N, L, L, S - prefix);
                if (L != R) root.set(1, 1, N, L + 1, R, C);
                if (R != N) {
                    long new_sum = (S - prefix) + (R - L) * C;
                    root.add(1, 1, N, R + 1, R + 1, old_sum - new_sum);
                }
            } else {
                int L, R;
                L = reader.nextInt(); R = reader.nextInt();
                qval ret = root.query(1, 1, N, L, R);
                int len = Math.max(ret.prefix_len, ret.subarray_len + 1);
                len = Math.max(len, ret.suffix_len + 1);
                len = Math.min(len, ret.len);
                out.write(Integer.toString(len));
                out.write("\n");
            }
        }
        out.flush();
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...