BZOJ3155: Preprefix sum

BZOJ3155: 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


题解Here!

 

树状数组神题。。。

开两个树状数组,第一个维护$val[i]$前缀和。

第二个维护$val[i]*(n-i+1)$的前缀和。

修改就是加上$x-val[i]$。

查询的话就是$query2(x)-query1(x)*(n-x)$。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 100010
using namespace std;
int n,m;
long long val[MAXN],bit_one[MAXN],bit_two[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline int lowbit(int x){return x&(-x);}
inline void update_one(int x,long long v){for(;x<=n;x+=lowbit(x))bit_one[x]+=v;}
inline long long query_one(int x){long long s=0;for(;x;x-=lowbit(x))s+=bit_one[x];return s;}
inline void update_two(int x,long long v){for(;x<=n;x+=lowbit(x))bit_two[x]+=v;}
inline long long query_two(int x){long long s=0;for(;x;x-=lowbit(x))s+=bit_two[x];return s;}
void work(){
	char ch[10];
	int x;
	while(m--){
		scanf("%s",ch);x=read();
		if(ch[0]=='M'){
			long long k=read();
			update_one(x,k-val[x]);
			update_two(x,(k-val[x])*(n-x+1));
			val[x]=k;
		}
		else printf("%lld\n",query_two(x)-query_one(x)*(n-x));
	}
}
void init(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		val[i]=read();
		update_one(i,val[i]);
		update_two(i,val[i]*(n-i+1));
	}
}
int main(){
	init();
	work();
    return 0;
}

 

posted @ 2018-08-19 10:25  符拉迪沃斯托克  阅读(171)  评论(0编辑  收藏  举报
Live2D