#include <bits/stdc++.h>
using namespace std;
const int MOD = 1'000'000'007;
struct Lin {
int a, b;
Lin operator *(const Lin& he) const {
int A = (long long) a * he.a % MOD;
int B = ((long long) b * he.a + he.b) % MOD;
return Lin{A, B};
}
};
int BASE = 1;
vector<Lin> tree;
Lin getLin(int L, int R) {
L += BASE;
R += BASE;
Lin left = tree[L];
Lin right{1, 0};
if (L != R) {
right = tree[R];
}
while (L + 1 < R) {
if (L % 2 == 0) {
left = left * tree[L+1];
}
if (R % 2 == 1) {
right = tree[R-1] * right;
}
L /= 2;
R /= 2;
}
return left * right;
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n, q;
cin >> n >> q;
BASE = 1;
while (BASE <= n) {
BASE *= 2;
}
tree.resize(2 * BASE);
vector<int> add(n), mul(n);
vector<long long> pref(n+1); // sum of add[i]
vector<int> positives; // sth that affects x=0
vector<int> muls; // sth that doubles x
for (int i = 0; i < n; i++) {
cin >> add[i] >> mul[i];
// assert(add[i] >= 0 && mul[i] >= 1);
tree[BASE+i] = (mul[i] >= 2 ? Lin{mul[i], 0} : Lin{1, add[i]});
if (add[i] > 0) {
positives.push_back(i);
}
if (mul[i] >= 2) {
muls.push_back(i);
}
pref[i+1] = pref[i] + add[i];
}
positives.push_back(n + 1);
for (int i = BASE - 1; i >= 1; --i) {
tree[i] = tree[2*i] * tree[2*i+1];
}
auto getSum = [&](int L, int R) {
// assert(L <= R + 1);
return pref[R+1] - pref[L];
};
while (q--) {
long long x;
int L, R;
cin >> x >> L >> R;
R--;
if (x == 0) {
L = *lower_bound(positives.begin(), positives.end(), L);
if (L > R) {
cout << "0\n";
continue;
}
}
if (x < MOD && L <= R) {
int z = lower_bound(muls.begin(), muls.end(), L) - muls.begin();
while (z < (int) muls.size() && muls[z] <= R && x < MOD) {
x += getSum(L, muls[z] - 1);
L = muls[z];
if (x >= MOD) {
break;
}
long long newX = max(x * mul[L], x + add[L]);
// assert(newX >= 2 * x && newX > x);
x = newX;
L++;
z++;
}
}
x %= MOD;
if (L <= R) {
Lin lin = getLin(L, R);
x = ((long long) x * lin.a + lin.b) % MOD;
}
cout << x % MOD << "\n";
}
}
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 100 101 102 103 104 105 106 107 108 109 110 | #include <bits/stdc++.h> using namespace std; const int MOD = 1'000'000'007; struct Lin { int a, b; Lin operator *(const Lin& he) const { int A = (long long) a * he.a % MOD; int B = ((long long) b * he.a + he.b) % MOD; return Lin{A, B}; } }; int BASE = 1; vector<Lin> tree; Lin getLin(int L, int R) { L += BASE; R += BASE; Lin left = tree[L]; Lin right{1, 0}; if (L != R) { right = tree[R]; } while (L + 1 < R) { if (L % 2 == 0) { left = left * tree[L+1]; } if (R % 2 == 1) { right = tree[R-1] * right; } L /= 2; R /= 2; } return left * right; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n, q; cin >> n >> q; BASE = 1; while (BASE <= n) { BASE *= 2; } tree.resize(2 * BASE); vector<int> add(n), mul(n); vector<long long> pref(n+1); // sum of add[i] vector<int> positives; // sth that affects x=0 vector<int> muls; // sth that doubles x for (int i = 0; i < n; i++) { cin >> add[i] >> mul[i]; // assert(add[i] >= 0 && mul[i] >= 1); tree[BASE+i] = (mul[i] >= 2 ? Lin{mul[i], 0} : Lin{1, add[i]}); if (add[i] > 0) { positives.push_back(i); } if (mul[i] >= 2) { muls.push_back(i); } pref[i+1] = pref[i] + add[i]; } positives.push_back(n + 1); for (int i = BASE - 1; i >= 1; --i) { tree[i] = tree[2*i] * tree[2*i+1]; } auto getSum = [&](int L, int R) { // assert(L <= R + 1); return pref[R+1] - pref[L]; }; while (q--) { long long x; int L, R; cin >> x >> L >> R; R--; if (x == 0) { L = *lower_bound(positives.begin(), positives.end(), L); if (L > R) { cout << "0\n"; continue; } } if (x < MOD && L <= R) { int z = lower_bound(muls.begin(), muls.end(), L) - muls.begin(); while (z < (int) muls.size() && muls[z] <= R && x < MOD) { x += getSum(L, muls[z] - 1); L = muls[z]; if (x >= MOD) { break; } long long newX = max(x * mul[L], x + add[L]); // assert(newX >= 2 * x && newX > x); x = newX; L++; z++; } } x %= MOD; if (L <= R) { Lin lin = getLin(L, R); x = ((long long) x * lin.a + lin.b) % MOD; } cout << x % MOD << "\n"; } } |
English