题目
n个数,q个操作(n,q<=1e5)
操作分两种,
1 l r 询问[l,r]区间内,的值
2 x y 把a[x]的值改成y
思路来源
凯神
题解
结构体维护三个值
sum:这一段的和 ans:这一段的答案 num:这一段的数字的个数
与合并的时候
sum和num可以直接合并,
而这一段的ans
心得
还是结构体的比较常用吖
配合函数传参这种的比较好写
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int n,q,a[maxn];
struct node
{
ll sum,ans,num;
node():sum(0),ans(0),num(0){
}
//sum:al+...+ar ans:l*al+...+ar num:r-l+1
}e[maxn*5];
node cal(node a,node b)
{
node ans;
ans.sum=a.sum+b.sum;
ans.num=a.num+b.num;
ans.ans=a.ans+b.ans+a.sum*b.num;
return ans;
}
void pushup(int p)
{
e[p]=cal(e[p<<1],e[p<<1|1]);
}
void build(int p,int l,int r)
{
if(l==r)
{
e[p].sum=e[p].ans=a[l];
e[p].num=1;
return;
}
int mid=(l+r)/2;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}
void update(int p,int l,int r,int x,int v)
{
if(l==r)
{
e[p].sum=e[p].ans=v;
return;
}
int mid=(l+r)/2;
if(x<=mid)update(p<<1,l,mid,x,v);
else update(p<<1|1,mid+1,r,x,v);
pushup(p);
}
node ask(int p,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)return e[p];
int mid=(l+r)/2;
node L,R,ans;
if(ql<=mid)L=ask(p<<1,l,mid,ql,qr);
if(qr>mid)R=ask(p<<1|1,mid+1,r,ql,qr);
ans=cal(L,R);
return ans;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
build(1,1,n);
while(q--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)printf("%lld\n",ask(1,1,n,x,y).ans);
else if(op==2)update(1,1,n,x,y);
}
return 0;
}