题解 CF1942F【Farmer John's Favorite Function】
wukaichen888 · · 题解
萌萌尺子,上大分。
首先,观察这个式子,发现
考虑以
每个块内维护
线段树上也同理维护
-
-
-
否则,
val_k\gets val_{rc} ,need_k\gets\inf 。
细节:保证最后一个块长度为
复杂度:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2e5+5,inf=4e18;
ll n,q,K=10,rev[N],a[N],pos[N],L[N],R[N],len;
ll msqrt(ll x){
for(ll i=sqrt(x)+3ll;;i--)
if(i*i<=x) return i;
}
struct node{ll val,ned;}tree[N];
#define lc k<<1
#define rc k<<1|1
#define ls lc,l,mid
#define rs rc,mid+1,r
void pushup(int k){
if(tree[lc].val>=tree[rc].ned){
tree[k].val=tree[rc].val+1;
tree[k].ned=inf;
}
else{
tree[k].val=tree[rc].val;
if(tree[lc].val+1==tree[rc].ned)
tree[k].ned=tree[lc].ned;
else
tree[k].ned=inf;
}
}
void build(int k){
ll l=L[rev[k]],r=R[rev[k]]; tree[k].val=0;
for(ll i=l;i<=r;i++) tree[k].val=msqrt(tree[k].val+a[i]);
tree[k].ned=tree[k].val+1;
for(ll i=r;i>=l;i--){
if(inf/tree[k].ned<=tree[k].ned){
tree[k].ned=inf;
return ;
}
tree[k].ned=tree[k].ned*tree[k].ned-a[i];
}
}
void pre(int k,int l,int r){
if(l==r){
rev[k]=l;
build(k);
return ;
}
int mid=l+r>>1;
pre(ls);pre(rs);
pushup(k);
}
void change(int k,int l,int r,int x){
if(l==r){
build(k);
return ;
}
int mid=l+r>>1;
if(x<=mid) change(ls,x);
else change(rs,x);
pushup(k);
}
int main(){
scanf("%lld%lld",&n,&q);
for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
len=(n-1)/K+1;
for(ll i=1;i<=n;i++) pos[i]=len-(n-i)/K;
for(ll i=1;i<=n;i++) R[pos[i]]=i;
for(ll i=n;i;i--) L[pos[i]]=i;
pre(1,1,len);
ll x,y;
while(q--){
scanf("%lld%lld",&x,&y);a[x]=y;
change(1,1,len,pos[x]);
printf("%lld\n",tree[1].val);
}
return 0;
}