3155: Preprefix sum
Time Limit: 1 Sec Memory Limit: 512 MBSubmit: 1820 Solved: 794
[Submit][Status][Discuss]
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
1 2 3 4 5
Query 5
Modify 3 2
Query 5
Sample Output
35
32
32
HINT
1<=N,M<=100000,且在任意时刻0<=Ai<=100000
Source
维护前缀和最有力的工具当然是树状数组了
我们维护题目上所说的两个树状数组a[i]的前缀和和a[i]*(n-i)的前缀和
#include <bits/stdc++.h> #define ll long long using namespace std; inline ll read(){ ll x=0;ll f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const ll MAXN=1e6+10; ll c[MAXN][3],n,m,a[MAXN]; inline ll lowbit(ll x){ return x&-x; } inline void change(ll xx,ll vv,ll val){ while(xx<=100000){ c[xx][val]+=vv; xx+=lowbit(xx); } } inline ll get(ll xx,ll val){ ll ans=0; while(xx){ ans+=c[xx][val]; xx-=lowbit(xx); } return ans; } void init(){ memset(c,0,sizeof(c)); n=read();m=read(); for(ll i=1;i<=n;i++){ a[i]=read(); change(i,a[i],0); change(i,(ll)(n-i+1)*a[i],1); } for(ll i=1;i<=m;i++){ char str[10]; scanf("%s",&str); //cout<<str[0]<<endl; if(str[0]=='M'){ ll xx=read();ll yy=read(); change(xx,yy-a[xx],0); change(xx,(ll)(yy-a[xx])*(n-xx+1),1); //cout<<a[xx]<<' '<<yy<<endl; a[xx]=yy; } else{ //cout<<1<<endl; ll xx=read(); printf("%lld ",get(xx,1)-get(xx,0)*(n-xx)); } } } int main(){ //freopen("All.in","r",stdin); //freopen("aa.out","w",stdout); init(); return 0; }