题意:给定n个数和q次查询,输入a,b,c,设L为b-c+1,若a=1,则求出,若a=2,则将第b个数替换成c。
思路:做题的时候发现只要求出两个值,总区间的和即 以及 ,前者-(n-c)*后者即可。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define maxn 100000+100
ll sum[maxn<<2];
ll sum1[maxn<<2];
ll n;
void pushup(ll rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
sum1[rt]=sum1[rt<<1]+sum1[rt<<1|1];
}
void build(ll l,ll r,ll rt)
{
if(l==r)
{
scanf("%d",&sum[rt]);
sum1[rt]=sum[rt];
sum[rt]*=(n-l+1);
return;
}
ll m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void update(ll q,ll change,ll l,ll r,ll rt)
{
if(l==r)
{
sum[rt]=change*(n-l+1);
sum1[rt]=change;
return;
}
ll m=(l+r)>>1;
if(q<=m)
update(q,change,l,m,rt<<1);
else
update(q,change,m+1,r,rt<<1|1);
pushup(rt);
}
ll query(ll x,ll y,ll l,ll r,ll rt)
{
if(x<=l&&y>=r)
return sum[rt];
ll m=(l+r)>>1;
ll ret=0;
if(x<=m)
ret+=query(x,y,l,m,rt<<1);
if(y>m)
ret+=query(x,y,m+1,r,rt<<1|1);
return ret;
}
ll query1(ll x,ll y,ll l,ll r,ll rt)
{
if(x<=l&&y>=r)
return sum1[rt];
ll m=(l+r)>>1;
ll ret=0;
if(x<=m)
ret+=query1(x,y,l,m,rt<<1);
if(y>m)
ret+=query1(x,y,m+1,r,rt<<1|1);
return ret;
}
int main()
{
ll q;
ll a,b,c;
ll ans;
while(~scanf("%lld%lld",&n,&q))
{
build(1,n,1);
while(q--)
{
ans=0;
scanf("%lld%lld%lld",&a,&b,&c);
if(a==1)
{
ans=query(b,c,1,n,1)- (n-c)*query1(b,c,1,n,1);
printf("%lld\n",ans);
}
else if(a==2)
{
update(b,c,1,n,1);
}
}
}
return 0;
}
线段树