[bzoj 3155] Preprefix sum
[bzoj 3155] Preprefix sum
Description
Input
第一行给出两个整数N,M。分别表示序列长度和操作个数
接下来一行有N个数,即给定的序列a1,a2,….an
接下来M行,每行对应一个操作,格式见题目描述
Output
对于每个询问操作,输出一行,表示所询问的SSi的值。
Sample Input
5 3
1 2 3 4 5
Query 5
Modify 3 2
Query 5
Sample Output
35
32
HINT
1<=N,M<=100000,且在任意时刻0<=Ai<=100000
唉,这题可以维护系数做,也可以直接用线段数搞.这里我用简单的方法,直接搞!我们直接维护sum[i]的值,那么询问pos相当于区间\([1,pos]\)的sum和.修改A[i]也好办,区间修改i~n的sum值就行了,改成加法的操作,就可以上线段树.不过也可以用拆一下SSi来用树状数组维护一下系数.有点麻烦,我不讲了.但是这里我用树状数组代替了线段树执行区间修改和区间查询的操作,至于这个是怎么来的,其实也有点像之前那个维护系数的方法,用差分的思路去做就好了.
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
static const int maxm = 1e5 + 10;
LL tr1[maxm],tr2[maxm],A[maxm],sum[maxm];
char ch[10];
int n,m,pos;
int lowbit(int x){
return x&-x;
}
void Upt(int k,LL val){
for(int i = k; i <= n ;i += lowbit(i))
tr1[i] += val,tr2[i] += 1LL * k * val;
}
LL Query(int k){
LL ret = 0;
for(int i = k ; i ;i -= lowbit(i))
ret += 1LL * (k+1) * tr1[i] - tr2[i];
return ret;
}
int main(){
LL x;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n ;i++)
scanf("%lld",&A[i]),sum[i]=sum[i-1]+A[i];
for(int i = 1;i <= n ;i++)
Upt(i,sum[i]),Upt(i+1,-sum[i]);
while(m--){
scanf("%s",ch);
if(ch[0]=='M'){
scanf("%d%lld",&pos,&x);
Upt(pos,x-A[pos]);Upt(n+1,A[pos]-x);
A[pos]=x;
}else{
scanf("%d",&pos);
printf("%lld\n",Query(pos));
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App