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
题解
随便推一下
其实就是要维护一个Sigma(a[i]*(n-i+1))的前缀和
那么这个前缀和这样是维护不了的
换一种思维,把里面拆开来
相当于Sigma(a[i]* n)-Sigma(a[i]* (i-1))
第一个维护一下a[i]的前缀和,第二个维护一下a[i]*(i-1)的前缀和
输出的时候把第一个前缀和集体乘一个输入的i,再减去第二个前缀和即可
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
LL s[110000][2];int n,m;
int lowbit(int x){return x&-x;}
void change(int x,LL c,int op)
{
while(x<=n)
{
s[x][op]+=c;
x+=lowbit(x);
}
}
LL findsum(int x,int op)
{
LL ret=0;
while(x>=1)
{
ret+=s[x][op];
x-=lowbit(x);
}
return ret;
}
char ss[10];
LL col[110000];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&col[i]);
change(i,col[i],0);
change(i,(i-1)*col[i],1);
}
while(m--)
{
int u;LL v;
scanf("%s%d",ss+1,&u);
if(ss[1]=='Q')printf("%lld\n",findsum(u,0)*u-findsum(u,1));
else
{
scanf("%lld",&v);
change(u,v-col[u],0);
change(u,(u-1)*(v-col[u]),1);
col[u]=v;
}
}
return 0;
}