題目描述
給定兩個長度爲 n 的序列 A 和 B,定義序列 \(C_i=\max\limits_{j=1}^i A_j\)ios
定義當前的價值是 $\prod\limits_{i=1}^n \min(B_i,C_i) $。spa
如今有 q 次操做,每次操做將會修改序列 A 或者 B 中的一個位置,將會把數字變大。如今請求出每次修改以後的價值。日誌
這題複雜度不許確code
錯誤日誌: while 用脫了。。, 之後用 while 判斷當前一個就好get
暴力修改
設修改區間爲 \([l, r]\) , 每次修改乘以 \(a_{i}\), 除以 \(b_{i}\), 咱們能夠在 \(O(n)\) 的時間內處理出
\[\frac{\prod_{i = l}^{r}a_{i}}{\prod_{i = l}^{r}b_{i}}\]
上一次答案乘上這個就是這一次的答案
而後要求分母的逆元, \(10^{9} + 7\) 爲質數, 用費馬小定理
而後這樣大概估一下複雜度上限是 \(O(n * (n + \log n))\)
因此數據貌似略水啊。。
當模擬練手了cmd
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #include<climits> #define LL long long #define REP(i, x, y) for(LL i = (x);i <= (y);i++) using namespace std; LL RD(){ LL out = 0,flag = 1;char c = getchar(); while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();} while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();} return flag * out; } const LL maxn = 2000019, M = 1e9 + 7; LL num, na; LL b[maxn], c[maxn]; LL ans = 1; LL get_inv(LL a){ LL p = M - 2, ans = 1; while(p){ if(p & 1)ans = ans * a % M; a = a * a % M; p >>= 1; } return ans % M; } void init(){ num = RD(), na = RD(); REP(i, 1, num)c[i] = max(c[i - 1], RD()); REP(i, 1, num)b[i] = RD(); REP(i, 1, num)ans = ans * min(c[i], b[i]) % M; } void solve(){ while(na--){ LL cmd = RD(), x = RD(), y = RD(); LL frac = 1, son = 1; if(cmd == 0){ while(c[x] < y){//把c[x]改成y if(c[x] < b[x]){ frac = frac * c[x] % M; son = son * min(y, b[x]) % M; } //else c'> c > b c[x] = y; x++; if(x > num)break; } } else{ if(b[x] < c[x]){//b[x] --> y frac = frac * b[x] % M; son = son * min(c[x], y) % M; } //else b'> b > c b[x] = y; } ans = ((ans * son) % M + M) % M; ans = ((ans * get_inv(frac)) % M + M) % M; printf("%lld\n", ans % M); } } int main(){ init(); solve(); return 0; }