题目传送门
题意解析:题目给了一个a序列,并且定义s为a序列的前缀和,ss为s序列的前缀和,然后有两种操作,一种是查询ss[i]的值,还有一种是修改a[i]。
My opinion:明显的数据结构题,但是怎么维护是一个问题,我们列出a,s,ss就会发现一些现象。
a a1 a2 a3 a4 a5 a6 …… an
s a1 a1+a2 a1+a2+a3 …… a1+a2+……+an
ss a1 2a1+a2 3a1+2a2+a3 …… na1+(n-1)a2+……+an
从上我们可以看出,每一个ai在一个ssj中(i<=j),ai有(j-i+1)个
所以这题我们只需要维护ai的前缀和和(n-i+1)*ai的前缀和就可以了。
最后答案的计算就是(n-i+1)*ai的前缀和减去ai的前缀和乘上(n-i)。
所以我们可以用各种数据结构维护,不过因为维护的区间是1-i(有可能没啥用),所以我用了树状数组。
总结:
1、输入,并加入树状数组。
2、对于每个操作做出相应的反应。
结构体大法好:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define Clear(a,x) memset(a,x,sizeof(a))
#define ll long long
#define INF 2000000000
#define eps 1e-8
using namespace std;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=100005;
int a[maxn];
int lowbit(int x){
return x&(-x);
}
int n,m;
struct tree{
ll tr[maxn];
inline void add(int x,ll d){
for (int i=x;i<=n;i+=lowbit(i))
tr[i]+=d;
}
inline ll sum(int x){
ll ans=0;
for (int i=x;i;i-=lowbit(i))
ans+=tr[i];
return ans;
}
}tr1,tr2;
int main(){
n=read(),m=read();
rep(i,1,n){
a[i]=read();
tr1.add(i,a[i]);
tr2.add(i,(ll)(n-i+1)*a[i]);
}
rep(i,1,m){
char op[10];
scanf("%s",op);
if (op[0]=='Q'){
int x=read();
printf("%lld\n",tr2.sum(x)-tr1.sum(x)*(n-x));
}else{
int x=read(),y=read();
tr1.add(x,y-a[x]);
tr2.add(x,(ll)(n-x+1)*(y-a[x]));
a[x]=y;
}
}
return 0;
}