結果

問題 No.1079 まお
ユーザー yosupotyosupot
提出日時 2020-06-12 21:59:47
言語 C++17
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 160 ms / 2,000 ms
コード長 12,183 bytes
コンパイル時間 1,455 ms
コンパイル使用メモリ 138,864 KB
実行使用メモリ 48,496 KB
最終ジャッジ日時 2023-09-06 10:25:56
合計ジャッジ時間 5,031 ms
ジャッジサーバーID
(参考情報)
judge12 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,380 KB
testcase_01 AC 2 ms
4,380 KB
testcase_02 AC 1 ms
4,380 KB
testcase_03 AC 2 ms
4,376 KB
testcase_04 AC 1 ms
4,380 KB
testcase_05 AC 1 ms
4,376 KB
testcase_06 AC 2 ms
4,376 KB
testcase_07 AC 3 ms
4,376 KB
testcase_08 AC 3 ms
4,380 KB
testcase_09 AC 3 ms
4,376 KB
testcase_10 AC 2 ms
4,376 KB
testcase_11 AC 3 ms
4,380 KB
testcase_12 AC 60 ms
12,932 KB
testcase_13 AC 51 ms
14,532 KB
testcase_14 AC 92 ms
18,396 KB
testcase_15 AC 85 ms
19,720 KB
testcase_16 AC 83 ms
21,208 KB
testcase_17 AC 112 ms
19,716 KB
testcase_18 AC 77 ms
19,408 KB
testcase_19 AC 141 ms
19,400 KB
testcase_20 AC 122 ms
19,528 KB
testcase_21 AC 105 ms
19,432 KB
testcase_22 AC 119 ms
23,296 KB
testcase_23 AC 124 ms
23,328 KB
testcase_24 AC 139 ms
23,328 KB
testcase_25 AC 160 ms
23,192 KB
testcase_26 AC 158 ms
23,204 KB
testcase_27 AC 38 ms
13,440 KB
testcase_28 AC 55 ms
23,152 KB
testcase_29 AC 93 ms
48,496 KB
testcase_30 AC 103 ms
48,460 KB
testcase_31 AC 31 ms
13,480 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

//#pragma GCC optimize("Ofast")
//#pragma GCC target("avx")
//#undef LOCAL




#include <algorithm>

#include <array>

#include <bitset>

#include <cassert>

#include <complex>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <map>

#include <numeric>

#include <queue>

#include <set>

#include <string>

#include <unordered_map>

#include <unordered_set>

#include <vector>

using namespace std;

using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;



#include <unistd.h>

struct Scanner {
    int fd = -1;
    char line[(1 << 15) + 1];
    size_t st = 0, ed = 0;
    void reread() {
        memmove(line, line + st, ed - st);
        ed -= st;
        st = 0;
        ed += ::read(fd, line + ed, (1 << 15) - ed);
        line[ed] = '\0';
    }
    bool succ() {
        while (true) {
            if (st == ed) {
                reread();
                if (st == ed) return false;
            }
            while (st != ed && isspace(line[st])) st++;
            if (st != ed) break;
        }
        if (ed - st <= 50) {
            bool sep = false;
            for (size_t i = st; i < ed; i++) {
                if (isspace(line[i])) {
                    sep = true;
                    break;
                }
            }
            if (!sep) reread();
        }
        return true;
    }
    template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
    bool read_single(T& ref) {
        if (!succ()) return false;
        while (true) {
            size_t sz = 0;
            while (st + sz < ed && !isspace(line[st + sz])) sz++;
            ref.append(line + st, sz);
            st += sz;
            if (!sz || st != ed) break;
            reread();
        }
        return true;
    }
    template <class T, enable_if_t<is_integral<T>::value, int> = 0>
    bool read_single(T& ref) {
        if (!succ()) return false;
        bool neg = false;
        if (line[st] == '-') {
            neg = true;
            st++;
        }
        ref = T(0);
        while (isdigit(line[st])) {
            ref = 10 * ref + (line[st++] & 0xf);
        }
        if (neg) ref = -ref;
        return true;
    }
    template <class T> bool read_single(V<T>& ref) {
        for (auto& d : ref) {
            if (!read_single(d)) return false;
        }
        return true;
    }
    void read() {}
    template <class H, class... T> void read(H& h, T&... t) {
        bool f = read_single(h);
        assert(f);
        read(t...);
    }
    Scanner(FILE* fp) : fd(fileno(fp)) {}
};

struct Printer {
  public:
    template <bool F = false> void write() {}
    template <bool F = false, class H, class... T>
    void write(const H& h, const T&... t) {
        if (F) write_single(' ');
        write_single(h);
        write<true>(t...);
    }
    template <class... T> void writeln(const T&... t) {
        write(t...);
        write_single('\n');
    }

    Printer(FILE* _fp) : fp(_fp) {}
    ~Printer() { flush(); }

  private:
    static constexpr size_t SIZE = 1 << 15;
    FILE* fp;
    char line[SIZE], small[50];
    size_t pos = 0;
    void flush() {
        fwrite(line, 1, pos, fp);
        pos = 0;
    }
    void write_single(const char& val) {
        if (pos == SIZE) flush();
        line[pos++] = val;
    }
    template <class T, enable_if_t<is_integral<T>::value, int> = 0>
    void write_single(T val) {
        if (pos > (1 << 15) - 50) flush();
        if (val == 0) {
            write_single('0');
            return;
        }
        if (val < 0) {
            write_single('-');
            val = -val; // todo min
        }
        size_t len = 0;
        while (val) {
            small[len++] = char(0x30 | (val % 10));
            val /= 10;
        }
        for (size_t i = 0; i < len; i++) {
            line[pos + i] = small[len - 1 - i];
        }
        pos += len;
    }
    void write_single(const string& s) {
        for (char c : s) write_single(c);
    }
    void write_single(const char* s) {
        size_t len = strlen(s);
        for (size_t i = 0; i < len; i++) write_single(s[i]);
    }
    template <class T> void write_single(const V<T>& val) {
        auto n = val.size();
        for (size_t i = 0; i < n; i++) {
            if (i) write_single(' ');
            write_single(val[i]);
        }
    }
};




template <class D, class Op> struct SimpleSeg {
    D e;
    Op op;
    int n, sz, lg; // size(extended to 2^i), lg
    V<D> d;

    SimpleSeg(const V<D>& v, D _e, Op _op) : e(_e), op(_op) {
        n = int(v.size());
        lg = 1;
        while ((1 << lg) < n) lg++;
        sz = 1 << lg;
        d = V<D>(2 * sz, e);
        for (int i = 0; i < n; i++) d[sz + i] = v[i];
        for (int i = sz - 1; i >= 0; i--) {
            update(i);
        }
    }

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }

    void set(int p, D x) {
        assert(0 <= p && p < n);
        p += sz;
        d[p] = x;
        for (int i = 1; i <= lg; i++) update(p >> i);
    }

    D single(int p) const {
        assert(0 <= p && p < n);
        return d[p + sz];
    }

    D sum(int a, int b) const {
        assert(a <= b);
        D sml = e, smr = e;
        a += sz;
        b += sz;

        while (a < b) {
            if (a & 1) sml = op(sml, d[a++]);
            if (b & 1) smr = op(d[--b], smr);
            a >>= 1;
            b >>= 1;
        }
        return op(sml, smr);
    }

    D all_sum() const {
        return d[1];
    }

    // min i s.t. f(d[a] + d[a+1] + ... d[i]) == true (or return n + 1)
    template <class Comp> int search_left(int a, Comp f) {
        a += sz;
        D sm = e;
        if (f(e)) return a;
        while (true) {
            if (f(op(sm, d[a]))) {
                while (a < sz) {
                    a *= 2;
                    if (!f(op(sm, d[a]))) {
                        sm = op(sm, d[a]);
                        a++;
                    }
                }
                a = a + 1 - sz;
                return a;
            }
            if (a & 1) {
                sm = op(sm, d[a]);
                a++;
                if ((a & -a) == a) break;
            }
            a >>= 1;
        }
        return n + 1;
    }
};

template <class D, class Op>
SimpleSeg<D, Op> get_simple_seg(V<D> v, D e, Op op) {
    return SimpleSeg<D, Op>(v, e, op);
}

template <class D, class L, class OpDD, class OpDL, class OpLL> struct SegTree {
    D e_d;
    L e_l;
    OpDD op_dd;
    OpDL op_dl;
    OpLL op_ll;
    int sz, lg; //(2^lgに拡張後の)サイズ, lg
    V<D> d;
    V<L> lz;

    SegTree(const V<D>& v,
            D _e_d,
            L _e_l,
            OpDD _op_dd,
            OpDL _op_dl,
            OpLL _op_ll)
        : e_d(_e_d), e_l(_e_l), op_dd(_op_dd), op_dl(_op_dl), op_ll(_op_ll) {
        int n = int(v.size());
        lg = 1;
        while ((1 << lg) < n) lg++;
        sz = 1 << lg;
        d = V<D>(2 * sz, e_d);
        lz = V<L>(2 * sz, e_l);
        for (int i = 0; i < n; i++) d[sz + i] = v[i];
        for (int i = sz - 1; i >= 0; i--) {
            update(i);
        }
    }

    void all_add(int k, L x) {
        d[k] = op_dl(d[k], x);
        lz[k] = op_ll(lz[k], x);
    }
    void push(int k) {
        all_add(2 * k, lz[k]);
        all_add(2 * k + 1, lz[k]);
        lz[k] = e_l;
    }
    void update(int k) { d[k] = op_dd(d[2 * k], d[2 * k + 1]); }

    void set(int p, D x) {
        p += sz;
        for (int i = lg; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= lg; i++) update(p >> i);
    }

    void add(int a, int b, L x, int l, int r, int k) {
        if (b <= l || r <= a) return;
        if (a <= l && r <= b) {
            all_add(k, x);
            return;
        }
        push(k);
        int mid = (l + r) / 2;
        add(a, b, x, l, mid, 2 * k);
        add(a, b, x, mid, r, 2 * k + 1);
        update(k);
    }
    void add(int a, int b, L x) { add(a, b, x, 0, sz, 1); }

    D single(int p) {
        p += sz;
        for (int i = lg; i >= 1; i--) push(p >> i);
        return d[p];
    }

    D sum(int a, int b, int l, int r, int k) {
        if (b <= l || r <= a) return e_d;
        if (a <= l && r <= b) return d[k];
        push(k);
        int mid = (l + r) / 2;
        return op_dd(sum(a, b, l, mid, 2 * k), sum(a, b, mid, r, 2 * k + 1));
    }
    D sum(int a, int b) { return sum(a, b, 0, sz, 1); }

    D all_sum() const { return d[1]; }
};

template <class D, class L, class OpDD, class OpDL, class OpLL>
SegTree<D, L, OpDD, OpDL, OpLL> get_seg(V<D> v,
                                        D e_d,
                                        L e_l,
                                        OpDD op_dd,
                                        OpDL op_dl,
                                        OpLL op_ll) {
    return SegTree<D, L, OpDD, OpDL, OpLL>(v, e_d, e_l, op_dd, op_dl, op_ll);
}

Scanner sc = Scanner(stdin);
Printer pr = Printer(stdout);

int main() {
    int n; ll val;
    sc.read(n, val);
    V<ll> a(n);
    for (int i = 0; i < n; i++) {
        sc.read(a[i]);
    }
    auto av = a;
    sort(av.begin(), av.end());
    av.erase(unique(av.begin(), av.end()), av.end());
    auto get_i = [&](ll x) {
        auto it = lower_bound(av.begin(), av.end(), x);
        if (it == av.end() || *it != x) return -1;
        return int(it - av.begin());
    };
    int L = int(av.size());

    using P = pair<ll, ll>;
    VV<P> sums(L, {P(-1, 0)}); // (idx, sum_idx)
    {
        V<int> bpos(L, 0);
        for (int i = 0; i < n; i++) {
            int idx = get_i(a[i]);
            ll bk = sums[idx].back().second;
            sums[idx].push_back(P(i, bk + bpos[idx]));
            bpos[idx] = i;
        }
        for (int idx = 0; idx < L; idx++) {
            ll bk = sums[idx].back().second;
            sums[idx].push_back(P(n, bk + bpos[idx]));
        }
    }


    V<P> ap(n);
    for (int i = 0; i < n; i++) {
        ap[i] = P(a[i], i);
    }
    auto seg = get_simple_seg(ap, P(TEN(10), -1), [&](P a, P b) { return min(a, b); });

    ll sum = 0;
    auto single = [&](int l, int mid, int r) {
        if (r - mid < mid - l) {
            for (int i = mid; i < r; i++) {
                int yi = get_i(val - a[i]);
                if (yi == -1) continue;

                int i1 = int(lower_bound(sums[yi].begin(), sums[yi].end(), P(l, -1)) - sums[yi].begin());
                int i2 = int(lower_bound(sums[yi].begin(), sums[yi].end(), P(mid + 1, -1)) - sums[yi].begin());

                ll c0 = i2 - i1;
                ll c1 = sums[yi][i2].second - sums[yi][i1].second;
                sum += c0 * (i + 1) - c1;
            }
        } else {
            for (int i = l; i <= mid; i++) {
                int yi = get_i(val - a[i]);
                if (yi == -1) continue;

                int i1 = int(lower_bound(sums[yi].begin(), sums[yi].end(), P(mid, -1)) - sums[yi].begin());
                int i2 = int(lower_bound(sums[yi].begin(), sums[yi].end(), P(r, -1)) - sums[yi].begin());

                ll c0 = i2 - i1;
                ll c1 = sums[yi][i2].second - sums[yi][i1].second;
                sum += c1 - c0 * (i - 1);
            }
        }
    };
    auto dfs = [&](auto self, int l, int r) {
        if (l == r) return;
        if (l + 1 == r) {
            if (2 * a[l] == val) {
                sum++;
            }
            return;
        }
        ll lw = seg.sum(l, r).first;
        V<int> lws = {l - 1};
        {
            int p = l;
            while (p < r) {
                auto x = seg.sum(p, r);
                if (x.first != lw) break;
                lws.push_back(int(x.second));
                p = int(x.second + 1);
            }
        }
        lws.push_back(r);
        int num = int(lws.size());
        for (int i = 1; i < num - 1; i++) {
            single(lws[i - 1] + 1, lws[i], lws[i + 1]);
        }
        for (int i = 0; i < num - 1; i++) {
            self(self, lws[i] + 1, lws[i + 1]);
        }
    };

    dfs(dfs, 0, n);

    pr.writeln(sum);
    return 0;
}
0