3155: Preprefix sum
Time Limit: 1 Sec Memory Limit: 512 MBSubmit: 1258 Solved: 573
[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
水题。
先考虑一下,若将题面中“将ai改为x”换成“ai加上x”,则对于其前缀和序列bi来说,是对bi-bn这段区间上所有数加x,对于查询前缀和的前缀和来说,实质是查询bi序列的某段和。
那么其实”将ai改为x“就是”ai加上x-ai“,按照上述思路,用线段树维护前缀和序列即可
附AC代码:
</pre><pre code_snippet_id="1962370" snippet_file_name="blog_20161102_1_9101974" name="code" class="cpp">
</pre><pre code_snippet_id="1962370" snippet_file_name="blog_20161102_1_9101974" name="code" class="cpp">
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<climits>
#define N 200001
#define M 1600001
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
ll n,m;char ch[101];
ll a[N],b[N],c[N];
struct edge{ll l,r,val,tag;}e[M];
void pushdown(ll u)
{
if(e[u].l==e[u].r)return;
if(e[u].tag)
{
ll tag=e[u].tag;
e[u<<1].val+=tag*(e[u<<1].r-e[u<<1].l+1);e[u<<1].tag+=tag;
e[u<<1|1].val+=tag*(e[u<<1|1].r-e[u<<1|1].l+1);e[u<<1|1].tag+=tag;
e[u].tag=0;
}
}
void pushup(ll u){e[u].val=e[u<<1].val+e[u<<1|1].val;}
void build(ll u,ll l,ll r)
{
e[u].l=l,e[u].r=r;
if(l==r){e[u].val=b[l];return;}
e[u].val=0;
ll mid=(l+r)>>1;
build(u<<1,l,mid);build(u<<1|1,mid+1,r);
pushup(u);
}
void change(ll u,ll x,ll y,ll c)
{
ll l=e[u].l,r=e[u].r;
pushdown(u);
if(x==l&&y==r)
{
e[u].tag+=c;
e[u].val+=c*(r-l+1);
return;
}
ll mid=(l+r)>>1;
if(y<=mid)change(u<<1,x,y,c);
else if(x>mid)change(u<<1|1,x,y,c);
else
{
change(u<<1,x,mid,c);
change(u<<1|1,mid+1,y,c);
}
pushup(u);
}
ll query(ll u,ll x,ll y)
{
ll l=e[u].l,r=e[u].r;
pushdown(u);
if(x<=l&&y>=r)return e[u].val;
ll mid=(l+r)>>1;
if(y<=mid)return query(u<<1,x,y);
else if(x>mid)return query(u<<1|1,x,y);
else return query(u<<1,x,mid)+query(u<<1|1,mid+1,y);
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("my.txt","w",stdout);
ll x;
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++){scanf("%lld",&a[i]);b[i]=b[i-1]+a[i];}
build(1,1,n);
for(ll i=1;i<=m;i++)
{
ll s,t;
scanf("%s%lld",ch,&s);
if(ch[0]=='M')
{
scanf("%lld",&t);
x=t-a[s];a[s]=t;
change(1,s,n,x);
}
else
printf("%lld\n",query(1,1,s));
}
}