BZOJ 3155: Preprefix sum( 线段树 )

刷刷水题... 

前缀和的前缀和...显然树状数组可以写...然而我不会, 只能写线段树了 

把改变成加, 然后线段树维护前缀和, 某点p加, 会影响前缀和pre(x)(p≤x≤n), 对[p, n]这段区间加即可, 然后query就求[1, p]的和即可 

---------------------------------------------------------------------------------

#include<bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
const int maxn = 100009;
 
int L, R, v, seq[maxn], N;
ll cnt[maxn];
 
struct Node {
Node *l, *r;
ll add, sum;
Node() {
add = 0;
}
inline void pushdown() {
if(add) {
l->add += add;
r->add += add;
add = 0;
}
}
inline void update(int len) {
if(l) sum = l->sum + r->sum;
sum += add * len;
if(!l) add = 0;
}
} pool[maxn << 1], *pt = pool, *root;
 
void build(Node* t, int l, int r) {
if(l == r) {
t->sum = cnt[l];
} else {
int m = (l + r) >> 1;
build(t->l = pt++, l, m);
build(t->r = pt++, m + 1, r);
t->update(r - l + 1);
}
}
 
void modify(Node* t, int l, int r) {
if(L <= l && r <= R) {
t->add += v;
} else {
t->pushdown();
int m = (l + r) >> 1;
L <= m ? modify(t->l, l, m) : t->l->update(m - l + 1);
m < R ? modify(t->r, m + 1, r) : t->r->update(r - m);
}
t->update(r - l + 1);
}
 
ll query(Node* t, int l, int r) {
if(L <= l && r <= R) return t->sum;
int m = (l + r) >> 1;
t->pushdown();
t->l->update(m - l + 1); t->r->update(r - m);
return (L <= m ? query(t->l, l, m) : 0) + (m < R ? query(t->r, m + 1, r) : 0);
}
 
int main() {
int m; scanf("%d%d", &N, &m);
for(int i = 1; i <= N; i++) scanf("%d", seq + i);
cnt[0] = 0;
for(int i = 1; i <= N; i++) cnt[i] += cnt[i - 1] + seq[i];
build(root = pt++, 1, N);
while(m--) {
char s[10]; scanf("%s", s);
if(s[0] == 'M') {
int p, v; scanf("%d%d", &p, &v);
::v = v - seq[p];
seq[p] = v;
L = p; R = N;
modify(root, 1, N);
} else {
L = 1;
  scanf("%d", &R);
printf("%lld\n", query(root, 1, N));
}
}
return 0;
}

--------------------------------------------------------------------------------- 

3155: Preprefix sum

Time Limit: 1 Sec  Memory Limit: 512 MB
Submit: 765  Solved: 341
[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

Sample Output

35
32

HINT

1<=N,M<=100000,且在任意时刻0<=Ai<=100000

Source

 

posted @ 2015-09-08 21:51  JSZX11556  阅读(381)  评论(0编辑  收藏  举报