Submission #1350240

#TimeUsernameProblemLanguageResultExecution timeMemory
1350240biankFibonacci representations (CEOI18_fib)C++20
65 / 100
1651 ms327680 KiB
#include <bits/stdc++.h>
 
using namespace std;
 
#define forsn(i, s, n) for (int i = int(s); i < int(n); i++)
#define forn(i, n) forsn(i, 0, n)
#define dforsn(i, s, n) for (int i = int(n) - 1; i >= int(s); i--)
#define dforn(i, n) dforsn(i, 0, n)
 
using vi = vector<int>;
using ii = pair<int, int>;
using vii = vector<ii>;
using ll = long long;
using ld = long double;
using vll = vector<ll>;
using vb = vector<bool>;
using pll = pair<ll, ll>;
using bint = __int128;
 
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
 
#define pb push_back
#define eb emplace_back
 
#define fst first
#define snd second
 
const int MOD = 1e9 + 7;
const int MAX_A = 1e9 + 50;
 
const int T = 2;

struct mat {
    int a00, a01, a10, a11;
    mat(int x, int y, int z, int w) : a00(x), a01(y), a10(z), a11(w) {}
};

const mat NEUTR = {1, 0, 0, 1};
 
mat mul(mat a, mat b) {
    return {
        (1LL * a.a00 * b.a00 + 1LL * a.a01 * b.a10) % MOD,
        (1LL * a.a00 * b.a01 + 1LL * a.a01 * b.a11) % MOD,
        (1LL * a.a10 * b.a00 + 1LL * a.a11 * b.a10) % MOD,
        (1LL * a.a10 * b.a01 + 1LL * a.a11 * b.a11) % MOD
    };
}
 
mat value(int x, int y) {
    return mul({1, y / 2, 0, 1}, {x / 2 + 1, x % 2, x / 2, x % 2});
}
 
vi vals;
set<ii> intervals;
 
const int INF = 1e9 + 2000;
 
using event = tuple<int, int, int>;
 
vector<vector<event>> events;
int t;
 
void addRange(int l, int r) {
    assert((r - l) % 2 == 0);
    if (l <= r) {
        events[t].eb(l, r, 1);
        intervals.emplace(l, r);
    }
}
 
void erase(auto it) {
    events[t].eb(it->fst, it->snd, 0);
    intervals.erase(it);
}
 
void add(int x) {
    auto it = intervals.upper_bound(make_pair(x, INF));
    auto [l, r] = *(--it);
    if (l <= x && x <= r) {
        if (l % 2 == x % 2) {
            erase(it);
            addRange(l + 1, x - 1);
            add(r + 1);
            if (l > 2) add(l - 2);
            else if (l == 2) add(l - 1);
        } else {
            addRange(l, x - 1);
            x = it->snd + 1;
            erase(it);
            add(x);
        }
    } else while (true) {
        auto right = intervals.upper_bound(make_pair(x, INF));
        auto left = prev(right);
        if (x == right->fst - 1) {
            x = right->snd + 1;
            erase(right);
            continue;
        }
        if (left->snd + 1 == x) {
            addRange(left->fst, left->snd - 2);
            erase(left);
            x++;
            continue;
        }
        ii curr{x, x};
        if (x == right->fst - 2) {
            curr.snd = right->snd;
            erase(right);
        }
        if (x == left->fst + 2) {
            curr.fst = left->fst;
            erase(left);
        }
        addRange(curr.fst, curr.snd);
        return;
    }
}
 
vector<mat> st;
int SZ;
 
void upd(int p, mat v) {
    for (st[p += SZ] = v; p /= 2; ) {
        st[p] = mul(st[2 * p + 1], st[2 * p]);
    }
}
 
int pos(int x) {
    auto it = lower_bound(all(vals), x);
    assert(it != end(vals) && *it == x);
    return int(it - begin(vals));
}
 
int main() {
    ios::sync_with_stdio(0); 
    cin.tie(0); cout.tie(0);
    
    int n;
    cin >> n;
    vi a(n);
    forn(i, n) cin >> a[i];
    
    intervals.emplace(-INF, -INF);
    intervals.emplace(INF, INF);
    events.resize(n);
    forn(i, n) {
        add(a[i]);
        t++;
    }
    
    vector<ii> allIntervals;
    forn(t, n) for (auto &[l, r, action] : events[t]) {
        if (action == 1) allIntervals.eb(l, r);
    }
    sort(all(allIntervals));
    allIntervals.erase(unique(all(allIntervals)), end(allIntervals));
    set<int> active;
    SZ = 1;
    while (SZ < sz(allIntervals)) SZ *= 2;
    st.assign(2 * SZ, NEUTR);
    forn(t, n) {
        for (auto [x, y, action] : events[t]) {
            int i = int(lower_bound(all(allIntervals), make_pair(x, y)) - begin(allIntervals));
            auto it = active.lower_bound(i);
            if (action == 1) {
                if (it != end(active)) {
                    int j = *it;
                    int len_j = allIntervals[j].snd - allIntervals[j].fst;
                    upd(j, value(allIntervals[j].fst - allIntervals[i].snd - 1, len_j));
                }
                int len_i = allIntervals[i].snd - allIntervals[i].fst;
                if (it != begin(active)) {
                    int j = *prev(it);
                    upd(i, value(allIntervals[i].fst - allIntervals[j].snd - 1, len_i));
                } else {
                    upd(i, value(allIntervals[i].fst - 1, len_i));
                }
                active.insert(i);
            } else {
                upd(i, NEUTR);
                it = active.erase(it);
                if (it != end(active)) {
                    i = *it;
                    int len = allIntervals[i].snd - allIntervals[i].fst;
                    if (it != begin(active)) {
                        int j = *prev(it);
                        upd(i, value(allIntervals[i].fst - allIntervals[j].snd - 1, len));
                    } else {
                        upd(i, value(allIntervals[i].fst - 1, len));
                    }
                }
            }
        }
        cout << st[1].a00 << "\n";
    }
    
    
    return 0;
}

Compilation message (stderr)

fib.cpp: In function 'mat mul(mat, mat)':
fib.cpp:43:53: warning: narrowing conversion of '((((1 * ((long long int)a.mat::a00)) * ((long long int)b.mat::a00)) + ((1 * ((long long int)a.mat::a01)) * ((long long int)b.mat::a10))) % ((long long int)((int)MOD)))' from 'long long int' to 'int' [-Wnarrowing]
   43 |         (1LL * a.a00 * b.a00 + 1LL * a.a01 * b.a10) % MOD,
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
fib.cpp:44:53: warning: narrowing conversion of '((((1 * ((long long int)a.mat::a00)) * ((long long int)b.mat::a01)) + ((1 * ((long long int)a.mat::a01)) * ((long long int)b.mat::a11))) % ((long long int)((int)MOD)))' from 'long long int' to 'int' [-Wnarrowing]
   44 |         (1LL * a.a00 * b.a01 + 1LL * a.a01 * b.a11) % MOD,
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
fib.cpp:45:53: warning: narrowing conversion of '((((1 * ((long long int)a.mat::a10)) * ((long long int)b.mat::a00)) + ((1 * ((long long int)a.mat::a11)) * ((long long int)b.mat::a10))) % ((long long int)((int)MOD)))' from 'long long int' to 'int' [-Wnarrowing]
   45 |         (1LL * a.a10 * b.a00 + 1LL * a.a11 * b.a10) % MOD,
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
fib.cpp:46:53: warning: narrowing conversion of '((((1 * ((long long int)a.mat::a10)) * ((long long int)b.mat::a01)) + ((1 * ((long long int)a.mat::a11)) * ((long long int)b.mat::a11))) % ((long long int)((int)MOD)))' from 'long long int' to 'int' [-Wnarrowing]
   46 |         (1LL * a.a10 * b.a01 + 1LL * a.a11 * b.a11) % MOD
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
#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...