CF992E 题解

1|0CF992E 题解

传送门 更好的阅读体验


简化题意:单点修改,设序列的前缀和序列是 si,查询是否存在一个 i 满足 ai=si1

1|1思路:


观察满足条件的数的个数。在不考虑 0 的情况下,如果一个 ai 满足条件,那么对于一个比他小的满足条件的数 aj,一定会有 aj=sj1,而 sj1+aj=sjsi1=ai,这就说明 2×ajai,因此满足条件的数至多有 O(logV) 个。如果考虑 0,那么任意一个在全零前缀里的数都满足条件,随便选一个就可以了。

因此,我们就可以暴力来找可能满足条件的数,即不断地找区间内最大的满足 si1aii ,常规做法是线段树上二分。而在本题中这个区间是一段前缀,可以直接在树状数组上二分,非常好写。

复杂度 O(nlognlogV)
const int N=200501; int n,Q; int a[N],Lg; ll c[N]; inline void add(int x,int y){for(;x<=n;x+=x&(-x))c[x]+=y;} inline pair<int,int> query(int x){ int k=0; ll sum=0; for(int i=Lg;~i;i--){ int cur=k|(1<<i); if(cur<=n&&sum+c[cur]<=x)sum+=c[cur],k=cur; } return make_pair(k,sum); } inline int query(){ if(a[1]==0)return 1; int cur=2e9; do{ cur>>=1; pair<int,int> tmp=query(cur); if(tmp.second==a[tmp.first+1]){ return tmp.first+1; } }while(cur); return -1; } int main(){ n=read(),Q=read(); Lg=log2(n); for(int i=1;i<=n;i++)a[i]=read(),add(i,a[i]); while(Q--){ int p=read(),x=read(); add(p,x-a[p]); a[p]=x; write(query());putchar('\n'); } return 0; }

 


__EOF__

本文作者Xttttr
本文链接https://www.cnblogs.com/Xttttr/p/17627033.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Xttttr  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示