#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll MOD = 1e9 + 7;
const int MAXN = 5e5 + 7;
int A[MAXN];
int B[MAXN];
ll pref[MAXN];
int nextA[MAXN];//nastepne a > 0
int nextB[MAXN];//nastepne b > 1
int n, q;
void wczytaj(){
cin >> n >> q;
for(int i = 1; i <= n; i++) cin >> A[i] >> B[i];
}
void precompute(){
for(int i = 1; i <= n; i++)
pref[i] = pref[i - 1] + (ll)A[i];
int lastA = n + 1;
int lastB = n + 1;
for(int i = n; i > 0; i--){
if(A[i] > 0) lastA = i;
nextA[i] = lastA;
if(B[i] > 1) lastB = i;
nextB[i] = lastB;
}
}
struct segTree{
int size;
vector<pair<ll, ll>> tree;
segTree(int n, int A[MAXN], int B[MAXN]){
size = 1 << (int)ceil(log2(n));
tree.assign(2*size, {1, 0});
for(int i = 1; i <= n; i++){
if(B[i] == 1) tree[i + size] = {1, (ll)A[i]};
else tree[i + size] = {(ll)B[i], 0};
}
for(int i = size - 1; i > 0; i--){
tree[i].first = (tree[2*i].first * tree[2*i+1].first) % MOD;
tree[i].second = (tree[2*i+1].second + tree[2*i].second * tree[2*i + 1].first) % MOD;
}
}
pair<ll, ll> query(int l, int r, int tmpL, int tmpR, int v){
if(tmpL >= l && tmpR <= r) return tree[v];
if(tmpL >= r || tmpR <= l) return {1, 0};
int mid = (tmpL + tmpR) / 2;
auto [lA, lB] = query(l, r, tmpL, mid, 2*v);
auto [rA, rB] = query(l, r, mid+1, tmpR, 2*v+1);
ll tmpA = (lA * rA) % MOD;
ll tmpB = ((lB * rA) % MOD + rB) % MOD;
return {tmpA, tmpB};
}
pair<ll, ll> query(int l, int r){
return query(l, r, 0, size - 1, 1);
}
};
int query(int x, int l, int r, segTree & tree){
ll ans = (ll)x;
int cur = l + 1;
while(cur <= r){
//teraz mnozymy - dla wyniku >= MOD i b > 1 zawsze sie oplaca
if(ans >= MOD){
ans %= MOD;
auto [a, b] = tree.query(cur, r);
ans = (ans * a + b) % MOD;
return ans;
}
//chcemy cos dodac
if(ans == 0){
int idx = nextA[cur];
if(idx > r) return 0;
ans = A[idx];
cur = idx + 1;
continue;
}
//skip b_i, ..., b_j = 1 - zawsze dodajemy
int idx = nextB[cur];
if(idx > r){//jedynki ida za koniec przedzialu
ans += pref[r] - pref[cur - 1];
return ans % MOD;
}
if(idx > cur){//koncza sie przed
ans += pref[idx - 1] - pref[cur - 1];
cur = idx;
continue;
}
//zachlannie - mozna bo odp < MOD
ans = max(ans + A[cur], ans * B[cur]);
cur++;
}
return ans % MOD;
}
int main(){
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
wczytaj();
precompute();
segTree tree(n+1, A, B);
int x, l, r;
while(q--){
cin >> x >> l >> r;
cout << query(x, l, r, tree) << "\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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | #include <bits/stdc++.h> using namespace std; #define ll long long const ll MOD = 1e9 + 7; const int MAXN = 5e5 + 7; int A[MAXN]; int B[MAXN]; ll pref[MAXN]; int nextA[MAXN];//nastepne a > 0 int nextB[MAXN];//nastepne b > 1 int n, q; void wczytaj(){ cin >> n >> q; for(int i = 1; i <= n; i++) cin >> A[i] >> B[i]; } void precompute(){ for(int i = 1; i <= n; i++) pref[i] = pref[i - 1] + (ll)A[i]; int lastA = n + 1; int lastB = n + 1; for(int i = n; i > 0; i--){ if(A[i] > 0) lastA = i; nextA[i] = lastA; if(B[i] > 1) lastB = i; nextB[i] = lastB; } } struct segTree{ int size; vector<pair<ll, ll>> tree; segTree(int n, int A[MAXN], int B[MAXN]){ size = 1 << (int)ceil(log2(n)); tree.assign(2*size, {1, 0}); for(int i = 1; i <= n; i++){ if(B[i] == 1) tree[i + size] = {1, (ll)A[i]}; else tree[i + size] = {(ll)B[i], 0}; } for(int i = size - 1; i > 0; i--){ tree[i].first = (tree[2*i].first * tree[2*i+1].first) % MOD; tree[i].second = (tree[2*i+1].second + tree[2*i].second * tree[2*i + 1].first) % MOD; } } pair<ll, ll> query(int l, int r, int tmpL, int tmpR, int v){ if(tmpL >= l && tmpR <= r) return tree[v]; if(tmpL >= r || tmpR <= l) return {1, 0}; int mid = (tmpL + tmpR) / 2; auto [lA, lB] = query(l, r, tmpL, mid, 2*v); auto [rA, rB] = query(l, r, mid+1, tmpR, 2*v+1); ll tmpA = (lA * rA) % MOD; ll tmpB = ((lB * rA) % MOD + rB) % MOD; return {tmpA, tmpB}; } pair<ll, ll> query(int l, int r){ return query(l, r, 0, size - 1, 1); } }; int query(int x, int l, int r, segTree & tree){ ll ans = (ll)x; int cur = l + 1; while(cur <= r){ //teraz mnozymy - dla wyniku >= MOD i b > 1 zawsze sie oplaca if(ans >= MOD){ ans %= MOD; auto [a, b] = tree.query(cur, r); ans = (ans * a + b) % MOD; return ans; } //chcemy cos dodac if(ans == 0){ int idx = nextA[cur]; if(idx > r) return 0; ans = A[idx]; cur = idx + 1; continue; } //skip b_i, ..., b_j = 1 - zawsze dodajemy int idx = nextB[cur]; if(idx > r){//jedynki ida za koniec przedzialu ans += pref[r] - pref[cur - 1]; return ans % MOD; } if(idx > cur){//koncza sie przed ans += pref[idx - 1] - pref[cur - 1]; cur = idx; continue; } //zachlannie - mozna bo odp < MOD ans = max(ans + A[cur], ans * B[cur]); cur++; } return ans % MOD; } int main(){ ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0); wczytaj(); precompute(); segTree tree(n+1, A, B); int x, l, r; while(q--){ cin >> x >> l >> r; cout << query(x, l, r, tree) << "\n"; } } |
English