#include <bits/stdc++.h>
using namespace std;
#define rep(a, b) for (int a = 0; a < (b); a++)
#define rep1(a, b) for (int a = 1; a <= (b); a++)
#define all(x) (x).begin(), (x).end()
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
const int MOD = 1e9 + 7;
const int LIM = 1<<19;
int n, q;
ll add[LIM], mul[LIM];
int jmp[LIM];
ll prefsum[LIM];
ll getsum(int l, int r) {
if (l > r) return 0;
return prefsum[r]-prefsum[l]+add[l];
}
const int TREESIZE = LIM<<1;
ll prodtree[TREESIZE];
ll tree[TREESIZE];
pii ivl[TREESIZE];
ll advance(ll start, ll dp, ll prod) {
return (start*prod + dp)%MOD;
}
void build(int v=1, int l=0, int r=LIM-1) {
if (l >= n) return;
ivl[v] = {l, r};
prodtree[v] = mul[l];
if (l == r) return;
int lv = 2*v;
int rv = 2*v+1;
int mid = (l+r)/2;
build(lv, l, mid);
build(rv, mid+1, r);
prodtree[v] = (prodtree[lv]*prodtree[rv])%MOD;
tree[v] = advance(tree[lv], tree[rv], prodtree[rv]);
}
vector<pll> leftupd;
vector<pll> rightupd;
ll que(ll cur, int l, int r) {
for (l+=LIM, r+=LIM+1; l<r; l>>=1, r>>=1) {
if (l&1) {
leftupd.push_back({tree[l], prodtree[l]});
l++;
}
if (r&1) {
r--;
rightupd.push_back({tree[r], prodtree[r]});
}
}
reverse(all(rightupd));
for (auto [dp, prod]: leftupd) cur = advance(cur, dp, prod);
for (auto [dp, prod]: rightupd) cur = advance(cur, dp, prod);
leftupd.clear();
rightupd.clear();
return cur;
}
int main() {
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> n >> q;
rep(i, n) cin >> add[i] >> mul[i];
int curidx = n;
for (int i = n-1; i >= 0; i--) {
if (mul[i] > 1) curidx = i;
jmp[i] = curidx;
}
ll sum = 0;
rep(i, n) {
sum += add[i];
prefsum[i] = sum;
}
rep(i, n) tree[LIM+i] = (mul[i] == 1 ? add[i] : 0);
build();
leftupd.reserve(1067);
rightupd.reserve(1067);
ll x;
int l, r;
rep(i, q) {
cin >> x >> l >> r;
if (x == 0) x += add[l++];
while (l<r && x<MOD) {
int jmpidx = min(r, jmp[l]);
x = x+getsum(l, jmpidx-1);
l = jmpidx;
if (l == r || x >= MOD) break;
x = max(x+add[l], x*mul[l]);
l++;
}
if (l == r) {
cout << x%MOD << "\n";
continue;
}
x = que(x%MOD, l, r-1);
cout << x << "\n";
}
return 0;
}
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 111 112 113 114 115 116 | #include <bits/stdc++.h> using namespace std; #define rep(a, b) for (int a = 0; a < (b); a++) #define rep1(a, b) for (int a = 1; a <= (b); a++) #define all(x) (x).begin(), (x).end() using ll = long long; using pii = pair<int, int>; using pll = pair<ll, ll>; const int MOD = 1e9 + 7; const int LIM = 1<<19; int n, q; ll add[LIM], mul[LIM]; int jmp[LIM]; ll prefsum[LIM]; ll getsum(int l, int r) { if (l > r) return 0; return prefsum[r]-prefsum[l]+add[l]; } const int TREESIZE = LIM<<1; ll prodtree[TREESIZE]; ll tree[TREESIZE]; pii ivl[TREESIZE]; ll advance(ll start, ll dp, ll prod) { return (start*prod + dp)%MOD; } void build(int v=1, int l=0, int r=LIM-1) { if (l >= n) return; ivl[v] = {l, r}; prodtree[v] = mul[l]; if (l == r) return; int lv = 2*v; int rv = 2*v+1; int mid = (l+r)/2; build(lv, l, mid); build(rv, mid+1, r); prodtree[v] = (prodtree[lv]*prodtree[rv])%MOD; tree[v] = advance(tree[lv], tree[rv], prodtree[rv]); } vector<pll> leftupd; vector<pll> rightupd; ll que(ll cur, int l, int r) { for (l+=LIM, r+=LIM+1; l<r; l>>=1, r>>=1) { if (l&1) { leftupd.push_back({tree[l], prodtree[l]}); l++; } if (r&1) { r--; rightupd.push_back({tree[r], prodtree[r]}); } } reverse(all(rightupd)); for (auto [dp, prod]: leftupd) cur = advance(cur, dp, prod); for (auto [dp, prod]: rightupd) cur = advance(cur, dp, prod); leftupd.clear(); rightupd.clear(); return cur; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> n >> q; rep(i, n) cin >> add[i] >> mul[i]; int curidx = n; for (int i = n-1; i >= 0; i--) { if (mul[i] > 1) curidx = i; jmp[i] = curidx; } ll sum = 0; rep(i, n) { sum += add[i]; prefsum[i] = sum; } rep(i, n) tree[LIM+i] = (mul[i] == 1 ? add[i] : 0); build(); leftupd.reserve(1067); rightupd.reserve(1067); ll x; int l, r; rep(i, q) { cin >> x >> l >> r; if (x == 0) x += add[l++]; while (l<r && x<MOD) { int jmpidx = min(r, jmp[l]); x = x+getsum(l, jmpidx-1); l = jmpidx; if (l == r || x >= MOD) break; x = max(x+add[l], x*mul[l]); l++; } if (l == r) { cout << x%MOD << "\n"; continue; } x = que(x%MOD, l, r-1); cout << x << "\n"; } return 0; } |
English