「CF992E」 Nastya and King-Shamans

题意

给定一个序列 \(a_i\) ,记其前缀和序列为 \(s_i\) ,有 \(q\) 个询问,每次单点修改,询问是否存在一个 \(i\) 满足 \(a_i=s_i−1\)​ ,有多解输出任意一个,无解输出 \(−1\) 。

分析

考虑一个很暴力的解法,每次修改都直接在原数组上改,然后再遍历一遍寻找答案,这样毫无疑问是 \(O(nq)\) 的。

但是可以发现一个性质:由于合法的 \(a_i\) 等于 \(s_{i-1}+1\) 且为正数,所以每个符合条件的 \(a_i\) 都会让前缀和倍增,所有数的总和是 \(s_n\),那么最多也只会有 \(\log s_n\) 个这样的 \(a_i\)

用线段树维护 \(a_i-s_{i-1}\) 的值,单次可以在最坏 \(\log n\log V\) 的情况下完成查询。

题目里的单点修改在这颗线段树上就是给 \(i\) 单点加,给 \([i+1,n]\) 区间减,用 lazy tag 就可以了,注意 \(i=n\) 时需跳过后面的区间减。

时间复杂度降到了 \(O(q\log n\log V)\),可以接受。

Code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define dbg(x) cout<<#x<<": "<<x<<"\n"
static char buf[100],*p1=buf,*p2=buf,obuf[100],*p3=obuf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++
#define putchar(x) (p3-obuf<100)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
inline ll read(){ll x=0,f=1;char c=getchar();while(c<48||c>57){if(c==45)f=0;c=getchar();}while(c>47&&c<58)x=(x<<3)+(x<<1)+(c^48),c=getchar();return f?x:-x;}
inline void write(ll x){if(!x){putchar(48);putchar('\n');return;}short top=0,s[40];if(x<0)x=-x,putchar(45);while(x)s[top++]=x%10^48,x/=10;while(top--)putchar(s[top]);putchar('\n');}
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((t[x].l+t[x].r)>>1)
const ll maxn=2e5+5;
ll n,q,res,a[maxn],s[maxn];
struct node{
    ll l,r,val,tag;
}t[maxn<<2];
inline void pushup(ll x){t[x].val=max(t[ls].val,t[rs].val);}
inline void pushdown(ll x){
    if(!t[x].tag)return;
    t[ls].tag+=t[x].tag,t[rs].tag+=t[x].tag;
    t[ls].val+=t[x].tag,t[rs].val+=t[x].tag;
    t[x].tag=0;
}
inline void build(ll x,ll l,ll r){
    t[x].l=l,t[x].r=r;
    if(l==r){
        t[x].val=a[l]-s[l-1];
        return;
    }
    build(ls,l,mid),build(rs,mid+1,r);
    pushup(x);
}
inline void update(ll x,ll l,ll r,ll k){
    if(l<=t[x].l&&t[x].r<=r){
        t[x].val+=k;t[x].tag+=k;
        return;
    }
    pushdown(x);
    if(l<=mid)update(ls,l,r,k);
    if(r>mid)update(rs,l,r,k);
    pushup(x);
}
inline void query(ll x){
    if(res!=-1)return;
    if(t[x].l==t[x].r){
        if(!t[x].val)res=t[x].l;
        return;
    }
    pushdown(x);
    if(t[ls].val>=0)query(ls);
    if(t[rs].val>=0)query(rs);
}
inline void solve(){
    n=read(),q=read();
    for(ll i=1;i<=n;++i)a[i]=read(),s[i]=s[i-1]+a[i];
    build(1,1,n);
    while(q--){
        ll pos=read(),k=read();
        update(1,pos,pos,k-a[pos]);
        if(pos<n)update(1,pos+1,n,a[pos]-k);
        a[pos]=k,res=-1;
        query(1);write(res);
    }
}
signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ll t=1;
    while(t--){
        solve();
    }
    fwrite(obuf,p3-obuf,1,stdout);
    return 0;
}
posted @ 2024-12-20 15:23  run-away  阅读(8)  评论(0)    收藏  举报