题解:P15574 [USACO26FEB] Milk Buckets S
每个桶向下倒的牛奶数量是一定的,那么每个桶向下倒固定次数后下面的桶会翻,所以每个桶向下倒的时间都成周期。
若桶
即
若桶
即
有了这两个值,最后的答案就可以简单计算了。
每次修改
但是直接写会有问题:周期太大存不下。解决方法也很简单,用线段树维护每个位置
AC code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5,inf=1e18+1;
int n,a[N],f[N],q,tr[N];
int mg(int x,int y){
if(x==inf||y==inf)return inf;
__int128 re=(__int128)x*y;
if(re>inf)return inf;
return (int)re;
}
void bd(int p,int l,int r){
if(l==r){tr[p]=f[l];return;}
int mi=l+r>>1;
bd(p<<1,l,mi),bd(p<<1|1,mi+1,r);
tr[p]=mg(tr[p<<1],tr[p<<1|1]);
}
void md(int p,int l,int r,int x,int v){
if(l==r){tr[p]=v;return;}
int mi=l+r>>1;
if(x<=mi)md(p<<1,l,mi,x,v);
else md(p<<1|1,mi+1,r,x,v);
tr[p]=mg(tr[p<<1],tr[p<<1|1]);
}
void pr(__int128 x){
if(x>9)pr(x/10);
cout<<char(x%10+'0');
}
signed main(){
ios::sync_with_stdio(0),cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
f[1]=a[1]+1;
for(int i=2;i<=n;i++)
f[i]=(a[i]+a[i-1]-1)/a[i-1];
bd(1,1,n),cin>>q;
while(q--){
int x,v,t;cin>>x>>v>>t,a[x]=v;
if(x==1){
f[1]=a[1]+1,md(1,1,n,1,f[1]);
if(n>=2){
f[2]=(a[2]+a[1]-1)/a[1];
md(1,1,n,2,f[2]);
}
}else if(x==n){
f[n]=(a[n]+a[n-1]-1)/a[n-1];
md(1,1,n,n,f[n]);
}else{
f[x]=(a[x]+a[x-1]-1)/a[x-1];
md(1,1,n,x,f[x]);
f[x+1]=(a[x+1]+a[x]-1)/a[x];
md(1,1,n,x+1,f[x+1]);
}
if(t<n-1){cout<<"0\n";continue;}
__int128 k=(t-n+1)/tr[1];
pr(k*a[n]),cout<<'\n';
}
return 0;
}