#include <iostream>
#include <vector>
#include <set>
#include <unordered_map>
#include <algorithm>
using namespace std;
const int P = 1'000'000'007;
struct segment_tree {
const int SIZE = 20;
vector<long long> elems;
segment_tree() {
elems.resize(1 << SIZE);
}
long long sum(long a, long b) {
return sum(a, b, 1, 0, 1 << (SIZE - 1));
}
long long sum(long a, long b, long u, long lo, long hi) {
if (a == lo && b == hi) return elems[u];
if (b <= a) return 0;
long mid = (lo + hi) / 2;
return sum(a, min(b, mid), 2 * u, lo, mid) + sum(max(a, mid), b, 2 * u + 1, mid, hi);
}
void add(long pos, long long v) {
pos += (1 << (SIZE - 1));
elems[pos] += v;
if (elems[pos] > P) elems[pos] -= P;
while (pos /= 2) {
elems[pos] = elems[2 * pos] + elems[2 * pos + 1];
if (elems[pos] > P) elems[pos] -= P;
}
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<long long> v;
v.resize(n);
for (int i = 0; i < n; ++i) {
cin >> v[i];
}
set<long long> s_even, s_odd;
vector<long long> even, odd;
long long base{};
for (int i = 0; i < n; ++i) {
base += v[i];
base %= P;
long long elem = v[i] - base;
if (elem < 0) elem += P;
(elem & 1 ? s_odd : s_even).insert(elem);
}
unordered_map<long long, int> pos;
int i = 0;
odd.resize(size(s_odd));
for (auto e: s_odd) {
odd[i] = e;
pos[e] = i++;
}
i = 0;
even.resize(size(s_even));
for (auto e: s_even) {
even[i] = e;
pos[e] = i++;
}
segment_tree odds{}, evens{};
base = 0;
long long to_add = 1;
for (int j = 0; j < n; ++j) {
base += v[j];
base %= P;
long long elem = v[j] - base;
if (elem < 0) elem += P;
(elem & 1 ? odds : evens).add(pos[elem], to_add);
if (base & 1) {
auto ep = lower_bound(begin(even), end(even), P - base) - begin(even);
auto op = lower_bound(begin(odd), end(odd), P - base) - begin(odd);
auto s1 = evens.sum(ep, (long) size(even));
auto s2 = odds.sum(0, op);
to_add = s1 + s2;
} else {
auto ep = lower_bound(begin(even), end(even), P - base) - begin(even);
auto op = lower_bound(begin(odd), end(odd), P - base + 1) - begin(odd);
auto s1 = evens.sum(0, ep);
auto s2 = odds.sum(op, (long) size(odd));
to_add = s1 + s2;
}
}
cout << (to_add % P);
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #include <iostream> #include <vector> #include <set> #include <unordered_map> #include <algorithm> using namespace std; const int P = 1'000'000'007; struct segment_tree { const int SIZE = 20; vector<long long> elems; segment_tree() { elems.resize(1 << SIZE); } long long sum(long a, long b) { return sum(a, b, 1, 0, 1 << (SIZE - 1)); } long long sum(long a, long b, long u, long lo, long hi) { if (a == lo && b == hi) return elems[u]; if (b <= a) return 0; long mid = (lo + hi) / 2; return sum(a, min(b, mid), 2 * u, lo, mid) + sum(max(a, mid), b, 2 * u + 1, mid, hi); } void add(long pos, long long v) { pos += (1 << (SIZE - 1)); elems[pos] += v; if (elems[pos] > P) elems[pos] -= P; while (pos /= 2) { elems[pos] = elems[2 * pos] + elems[2 * pos + 1]; if (elems[pos] > P) elems[pos] -= P; } } }; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<long long> v; v.resize(n); for (int i = 0; i < n; ++i) { cin >> v[i]; } set<long long> s_even, s_odd; vector<long long> even, odd; long long base{}; for (int i = 0; i < n; ++i) { base += v[i]; base %= P; long long elem = v[i] - base; if (elem < 0) elem += P; (elem & 1 ? s_odd : s_even).insert(elem); } unordered_map<long long, int> pos; int i = 0; odd.resize(size(s_odd)); for (auto e: s_odd) { odd[i] = e; pos[e] = i++; } i = 0; even.resize(size(s_even)); for (auto e: s_even) { even[i] = e; pos[e] = i++; } segment_tree odds{}, evens{}; base = 0; long long to_add = 1; for (int j = 0; j < n; ++j) { base += v[j]; base %= P; long long elem = v[j] - base; if (elem < 0) elem += P; (elem & 1 ? odds : evens).add(pos[elem], to_add); if (base & 1) { auto ep = lower_bound(begin(even), end(even), P - base) - begin(even); auto op = lower_bound(begin(odd), end(odd), P - base) - begin(odd); auto s1 = evens.sum(ep, (long) size(even)); auto s2 = odds.sum(0, op); to_add = s1 + s2; } else { auto ep = lower_bound(begin(even), end(even), P - base) - begin(even); auto op = lower_bound(begin(odd), end(odd), P - base + 1) - begin(odd); auto s1 = evens.sum(0, ep); auto s2 = odds.sum(op, (long) size(odd)); to_add = s1 + s2; } } cout << (to_add % P); } |
English