/*
* Kamil Debowski
* O(n log(n)), the intended solution.
* Finds all changes of intervals offline and then builds a segment tree over them.
* No BST.
*/
#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9 + 1000; // must be bigger than max(A[i]) + log(n)
const int mod = 1e9 + 7;
set<pair<int,int>> intervals; // pairs of indices (A, B) such that A,A+2,A+4,...,B are all 1's
vector<vector<pair<int,int>>> events;
int current_time;
void add_if_not_empty(int a, int b) {
assert((b - a) % 2 == 0);
if(a <= b) {
assert(0 <= a && b < INF);
events[current_time].push_back({a, b});
intervals.insert({a, b});
}
}
void erase(set<pair<int,int>> :: iterator it) {
events[current_time].push_back({it -> first, it -> second});
intervals.erase(it);
}
void add_outside(const int x) {
auto R = intervals.upper_bound({x, INF});
if(x + 1 == R -> first) { // just before the interval R
// the whole interval is compressed to R->second+1
const int new_value = R -> second + 1;
erase(R);
add_outside(new_value);
return;
}
auto L = prev(R);
if(L -> second + 1 == x) { // just after the interval L
// erase the last element of L
add_if_not_empty(L -> first, L -> second - 2);
erase(L);
add_outside(x + 1);
return;
}
pair<int,int> new_interval{x, x};
if(x + 2 == R -> first) {
new_interval.second = R -> second;
erase(R);
}
if(L -> second + 2 == x) {
new_interval.first = L -> first;
erase(L);
}
add_if_not_empty(new_interval.first, new_interval.second);
}
void add_possibly_inside(const int x) {
auto it = intervals.upper_bound({x, INF});
it--;
if(!(it -> first <= x && x <= it -> second)) {
add_outside(x);
return;
}
// now we know that 'x' is inside the interval
assert(0 <= it -> first && it -> second < INF);
if(it -> first % 2 != x % 2) {
/*
* ...0001010101010100...
* + 1
* = ...0001010100000010...
*/
add_if_not_empty(it -> first, x - 1);
const int new_value = it -> second + 1;
erase(it);
add_outside(new_value);
return;
}
/*
* ...0001010101010100...
* + 1
* = ...0100101011010100...
* = ...0100101000000010...
*/
const vector<int> new_values{it -> first - 2, it -> second + 1};
add_if_not_empty(it -> first + 1, x - 1);
erase(it);
for(int a : new_values) {
if(a == -2) continue; // Fib[-2] = 0
if(a == -1) a = 0; // Fib[-1] = Fib[0]
add_outside(a);
}
}
struct M {
#define REP(i) for(int i = 0; i < 2; ++i)
int m[2][2]; // m[A][B] = m[rightmost bit can be not-changed][leftmost bit...]
int * operator [] (int i) { return m[i]; }
const int * operator [] (int i) const { return m[i]; }
M() { REP(i) REP(j) m[i][j] = 0; }
M operator * (const M & b) const {
M r;
REP(i) REP(j) REP(k)
r[i][k] = (r[i][k] + (long long) m[i][j] * b[j][k]) % mod;
return r;
}
#undef REP
};
struct S {
bool exists = false;
M m;
int low, high;
void init(pair<int,int> p) {
low = p.first, high = p.second;
int size = (high - low) / 2 + 1;
m[0][0] = 1;
m[0][1] = 0;
m[1][0] = size - 1;
m[1][1] = 1;
}
void merge(const S & A, const S & B) {
exists = A.exists || B.exists;
if(!A.exists) {
*this = B;
return;
}
if(!B.exists) {
*this = A;
return;
}
low = A.low;
high = B.high;
const int dist = B.low - A.high;
//~ assert(dist >= 3);
M mid;
if(dist % 2 == 0) {
mid[0][0] = 1;
mid[1][0] = 1;
}
mid[0][1] = mid[1][1] = max(0, (dist - 1) / 2);
mid[1][1] = (mid[1][1] + 1) % mod;
m = (B.m * mid) * A.m;
}
};
int main() {
int n;
scanf("%d", &n);
events.resize(n);
intervals.insert({-4, -4});
intervals.insert({INF, INF}); // to simplify the implementation
for(current_time = 0; current_time < n; ++current_time) {
int ai;
scanf("%d", &ai);
--ai;
add_possibly_inside(ai);
}
vector<pair<int,int>> all;
for(const vector<pair<int,int>> & vec : events)
for(const pair<int,int> & p : vec)
all.push_back(p);
sort(all.begin(), all.end());
all.resize(unique(all.begin(),all.end()) - all.begin());
int pot = 1;
while(pot < (int) all.size()) pot *= 2;
vector<S> tr(2 * pot);
for(int i = 0; i < (int) all.size(); ++i)
tr[pot+i].init(all[i]);
S START;
START.init({-1, -1});
START.exists = true;
for(current_time = 0; current_time < n; ++current_time) {
for(pair<int,int> p : events[current_time]) {
int i = lower_bound(all.begin(), all.end(), p) - all.begin();
tr[pot+i].exists = !tr[pot+i].exists;
for(int x = (pot + i) / 2; x >= 1; x /= 2)
tr[x].merge(tr[2*x], tr[2*x+1]);
}
S total;
total.merge(START, tr[1]);
printf("%d\n", total.m[1][1]);
}
}
Compilation message
fib.cpp: In function 'int main()':
fib.cpp:151:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
151 | scanf("%d", &n);
| ~~~~~^~~~~~~~~~
fib.cpp:157:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
157 | scanf("%d", &ai);
| ~~~~~^~~~~~~~~~~
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
1 ms |
600 KB |
Output is correct |
2 |
Correct |
0 ms |
348 KB |
Output is correct |
3 |
Correct |
0 ms |
348 KB |
Output is correct |
4 |
Correct |
0 ms |
348 KB |
Output is correct |
5 |
Correct |
0 ms |
348 KB |
Output is correct |
6 |
Correct |
0 ms |
348 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
1 ms |
600 KB |
Output is correct |
2 |
Correct |
0 ms |
348 KB |
Output is correct |
3 |
Correct |
0 ms |
348 KB |
Output is correct |
4 |
Correct |
0 ms |
348 KB |
Output is correct |
5 |
Correct |
0 ms |
348 KB |
Output is correct |
6 |
Correct |
0 ms |
348 KB |
Output is correct |
7 |
Correct |
1 ms |
348 KB |
Output is correct |
8 |
Correct |
0 ms |
348 KB |
Output is correct |
9 |
Correct |
0 ms |
348 KB |
Output is correct |
10 |
Correct |
0 ms |
348 KB |
Output is correct |
11 |
Correct |
0 ms |
436 KB |
Output is correct |
12 |
Correct |
1 ms |
348 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
0 ms |
348 KB |
Output is correct |
2 |
Correct |
0 ms |
348 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
1 ms |
600 KB |
Output is correct |
2 |
Correct |
0 ms |
348 KB |
Output is correct |
3 |
Correct |
0 ms |
348 KB |
Output is correct |
4 |
Correct |
0 ms |
348 KB |
Output is correct |
5 |
Correct |
0 ms |
348 KB |
Output is correct |
6 |
Correct |
0 ms |
348 KB |
Output is correct |
7 |
Correct |
1 ms |
348 KB |
Output is correct |
8 |
Correct |
0 ms |
348 KB |
Output is correct |
9 |
Correct |
0 ms |
348 KB |
Output is correct |
10 |
Correct |
0 ms |
348 KB |
Output is correct |
11 |
Correct |
0 ms |
436 KB |
Output is correct |
12 |
Correct |
1 ms |
348 KB |
Output is correct |
13 |
Correct |
0 ms |
348 KB |
Output is correct |
14 |
Correct |
0 ms |
348 KB |
Output is correct |
15 |
Correct |
1 ms |
348 KB |
Output is correct |
16 |
Correct |
0 ms |
348 KB |
Output is correct |
17 |
Correct |
0 ms |
348 KB |
Output is correct |
18 |
Correct |
0 ms |
348 KB |
Output is correct |
19 |
Correct |
0 ms |
348 KB |
Output is correct |
20 |
Correct |
0 ms |
348 KB |
Output is correct |
21 |
Correct |
1 ms |
348 KB |
Output is correct |
22 |
Correct |
0 ms |
348 KB |
Output is correct |
23 |
Correct |
1 ms |
348 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
0 ms |
604 KB |
Output is correct |
2 |
Correct |
136 ms |
20524 KB |
Output is correct |
3 |
Correct |
141 ms |
19400 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
1 ms |
600 KB |
Output is correct |
2 |
Correct |
0 ms |
348 KB |
Output is correct |
3 |
Correct |
0 ms |
348 KB |
Output is correct |
4 |
Correct |
0 ms |
348 KB |
Output is correct |
5 |
Correct |
0 ms |
348 KB |
Output is correct |
6 |
Correct |
0 ms |
348 KB |
Output is correct |
7 |
Correct |
1 ms |
348 KB |
Output is correct |
8 |
Correct |
0 ms |
348 KB |
Output is correct |
9 |
Correct |
0 ms |
348 KB |
Output is correct |
10 |
Correct |
0 ms |
348 KB |
Output is correct |
11 |
Correct |
0 ms |
436 KB |
Output is correct |
12 |
Correct |
1 ms |
348 KB |
Output is correct |
13 |
Correct |
0 ms |
348 KB |
Output is correct |
14 |
Correct |
0 ms |
348 KB |
Output is correct |
15 |
Correct |
1 ms |
348 KB |
Output is correct |
16 |
Correct |
0 ms |
348 KB |
Output is correct |
17 |
Correct |
0 ms |
348 KB |
Output is correct |
18 |
Correct |
0 ms |
348 KB |
Output is correct |
19 |
Correct |
0 ms |
348 KB |
Output is correct |
20 |
Correct |
0 ms |
348 KB |
Output is correct |
21 |
Correct |
1 ms |
348 KB |
Output is correct |
22 |
Correct |
0 ms |
348 KB |
Output is correct |
23 |
Correct |
1 ms |
348 KB |
Output is correct |
24 |
Correct |
0 ms |
604 KB |
Output is correct |
25 |
Correct |
136 ms |
20524 KB |
Output is correct |
26 |
Correct |
141 ms |
19400 KB |
Output is correct |
27 |
Correct |
38 ms |
6080 KB |
Output is correct |
28 |
Correct |
79 ms |
10448 KB |
Output is correct |
29 |
Correct |
36 ms |
5944 KB |
Output is correct |
30 |
Correct |
70 ms |
10068 KB |
Output is correct |
31 |
Correct |
80 ms |
17344 KB |
Output is correct |
32 |
Correct |
79 ms |
11208 KB |
Output is correct |
33 |
Correct |
111 ms |
16080 KB |
Output is correct |
34 |
Correct |
110 ms |
17344 KB |
Output is correct |
35 |
Correct |
139 ms |
15676 KB |
Output is correct |
36 |
Correct |
179 ms |
16060 KB |
Output is correct |
37 |
Correct |
146 ms |
9672 KB |
Output is correct |
38 |
Correct |
141 ms |
20468 KB |
Output is correct |
39 |
Correct |
48 ms |
8660 KB |
Output is correct |
40 |
Correct |
88 ms |
13172 KB |
Output is correct |
41 |
Correct |
221 ms |
13180 KB |
Output is correct |
42 |
Correct |
124 ms |
20424 KB |
Output is correct |
43 |
Correct |
93 ms |
13752 KB |
Output is correct |
44 |
Correct |
156 ms |
32136 KB |
Output is correct |
45 |
Correct |
195 ms |
32608 KB |
Output is correct |
46 |
Correct |
187 ms |
31620 KB |
Output is correct |
47 |
Correct |
189 ms |
22204 KB |
Output is correct |
48 |
Correct |
201 ms |
33460 KB |
Output is correct |
49 |
Correct |
261 ms |
31804 KB |
Output is correct |
50 |
Correct |
181 ms |
20804 KB |
Output is correct |