LG4868 Preprefix sum 题解
壹、题目大意
给出长度为
可以给定
贰、思路
这道题查询的是
因此考虑维护
由上文,修改
查询
因此操作二实际上就是对
由此,我们可以想到线段树、分块、树状数组等做法
线段树时间复杂度
分块时间复杂度
树状数组的话时间复杂度
因此优先考虑树状数组
对于区间修改我们看到修改的是
因此考虑好数据结构,还要再思考一个问题:如何把题目中问的与
OI中,推导式子是一个常态
遇到这种有累加值的题目,我们可以首先把题目中的原式转化成与输入的
然后我们举一些特殊例子来判断:
…………
然后我们可以发现,对于一个
那它的 贡献 便是它本身的数值乘上它在前缀和里面出现的次数,即
每个
所以
拆开,得到
拆到这里,想必大家都明白了,这里有两个前缀和:
所以我们需要维护两个树状数组,一个里面是
然后按照这个式子写出来即可
(注意树状数组大小范围)
叄、代码
#include<bits/stdc++.h> #define endl "\n" #define int long long//要开 long long using namespace std; const int N=100009; int n,m; int a[N]; class tree_array { private: int s[N<<1]; inline int lowbit(int x){return x&(-x);} public://模板操作 inline void add(int point,int val) { for(int i=point;i<=(n<<1);i+=lowbit(i)) s[i]+=val; return; } inline int query(int point) { int res=0; for(int i=point;i>=1;i-=lowbit(i)) res+=s[i]; return res; } }bit1,bit2; //bit1 维护 aj,bit2 维护 aj*j signed main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); //freopen("sum.in","r",stdin); //freopen("sum.out","w",stdout); cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i];//输入 for(int i=1;i<=n;i++) { bit1.add(i,a[i]); bit2.add(i,a[i]*i);//建立树状数组 } while(m--) { string str; int u,x; cin>>str>>u; if(str=="Modify") { cin>>x; bit1.add(u,x-a[u]); bit2.add(u,(x-a[u])*u);//修改一下 a[u]=x; } else { int res=(u+1)*bit1.query(u)-bit2.query(u);//按照推的式子输出即可 cout<<res<<endl; } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效