UOJ232【IOI2015】Horses【线段树】
给定长为 \(n\) 的序列 \(x_0,x_1,\cdots,x_{n-1};y_0,y_1,\cdots,y_{n-1}\)。
Catcats 在养猫猫,第 \(0\) 年有 \(1\) 只猫猫。若第 \(i\) 年初始有 \(k\) 只猫猫,则第 \(i\) 年末尾时有 \(x_ik\) 只猫猫。
第 \(i\) 年末尾时可以卖任意多只猫猫,每只猫猫 \(y_i\) 元。
支持 \(m\) 次单点修改并求最大收益\(\bmod(10^9+7)\)。
\(n\le 5\cdot 10^5,m\le 10^5\)。
答案即为 \(\max\{y_i\prod_{j=1}^ix_j\mid i\in[1,n]\}\)。直接用线段树维护即可。
坑:zkw 线段树建树时要跑满。
#include"horses.h"
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int M = 1<<19, N = M<<1, mod = 1e9 + 7;
int s[N], v[N], X[N], Y[N]; double S[N], V[N];
void upd(int p, int x, int y){
p += M; s[p] = x; v[p] = (LL)x * y % mod;
S[p] = log(x); V[p] = S[p] + log(y); p >>= 1;
while(p){
int ls = p<<1, rs = ls|1;
s[p] = (LL)s[ls] * s[rs] % mod;
S[p] = S[ls] + S[rs];
if(V[ls] > S[ls] + V[rs]){
V[p] = V[ls]; v[p] = v[ls];
} else {
V[p] = S[ls] + V[rs];
v[p] = (LL)s[ls] * v[rs] % mod;
} p >>= 1;
}
} int init(int n, int x[], int y[]){
upd(0, 1, 0);
for(int i = 1;i <= n;++ i) upd(i, X[i] = x[i-1], Y[i] = y[i-1]);
for(int i = n+1;i < M;++ i) upd(i, 0, 0);
return v[1];
} int updateX(int pos, int val){
++ pos; upd(pos, X[pos] = val, Y[pos]); return v[1];
} int updateY(int pos, int val){
++ pos; upd(pos, X[pos], Y[pos] = val); return v[1];
}