Ryuji doesn't want to study

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lpeaceminusone/article/details/82622248

Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, each book has its knowledge a[i]a[i].

Unfortunately, the longer he learns, the fewer he gets.

That means, if he reads books from ll to rr, he will get a[l] \times L + a[l+1] \times (L-1) + \cdots + a[r-1] \times 2 + a[r]a[l]×L+a[l+1]×(L−1)+⋯+a[r−1]×2+a[r] (LL is the length of [ ll, rr ] that equals to r - l + 1r−l+1).

Now Ryuji has qq questions, you should answer him:

11. If the question type is 11, you should answer how much knowledge he will get after he reads books [ ll, rr ].

22. If the question type is 22, Ryuji will change the ith book's knowledge to a new value.

Input

First line contains two integers nn and qq (nn, q \le 100000q≤100000).

The next line contains n integers represent a[i]( a[i] \le 1e9)a[i](a[i]≤1e9) .

Then in next qq line each line contains three integers aa, bb, cc, if a = 1a=1, it means question type is 11, and bb, ccrepresents [ ll , rr ]. if a = 2a=2 , it means question type is 22 , and bb, cc means Ryuji changes the bth book' knowledge to cc

Output

For each question, output one line with one integer represent the answer.

样例输入复制

5 3
1 2 3 4 5
1 1 3
2 5 0
1 4 5

样例输出复制

10
8

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

线段树

先把前缀和存下来,在更新和查询

#include<map>
#include<stack>
#include<queue>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#define mem(a,b) memset(b,sizeof(a),b)
#define LL long long
#define inf 0x3f3f3f
#define root  1,n,1
#define lson  l,mid,rt<<1
#define rson  mid+1,r,rt<<1|1
#define lcvalue(rt) (lazy[rt<<1]*(mid-l+1)+sum[rt<<1])
#define rcvalue(rt) (lazy[rt<<1|1]*(r-mid)+sum[rt<<1|1])
#define PushUp(rt) sum[rt] = lcvalue(rt)+ rcvalue(rt)
using namespace std;
const int maxn=100115;
LL sum[maxn<<2];
LL lazy[maxn<<2];
int n,m,p;
LL a[maxn],b[maxn];

void Build(int l,int r,int rt)//建树
{
    if(l==r){
      sum[rt]=b[p++];
        return ;
    }
    int mid=(l+r)>>1;
    Build(lson);//建左儿子
    Build(rson);//右儿子
    PushUp(rt);//更新
}
void Update(int ll,int rr,LL c,int l,int r,int rt)//区间更新
{
    if(l==r){
        sum[rt]+=c;return ;
    }
    if(ll<=l&&rr>=r)//找到相应区间直接返回sum
    {
        lazy[rt]+=c;
        return ;
    }
    int mid=(l+r)>>1;
    if(ll<=mid)  Update(ll,rr,c,lson);//在左儿子中找区间
    if(rr>mid)   Update(ll,rr,c,rson);//在右儿子中找
    PushUp(rt);//向上更新sum;
}
LL  Query(int ll,int rr,int l,int r,int rt,LL z)//区间查询
{
    //cout<<ll<<" "<<rr<<" "<<l<<" "<<r<<" "<<rt<<" "<<z<<endl;
    lazy[rt]+=z;
    if(ll>r||rr<l)return 0;
    if(ll<=l&&rr>=r)return sum[rt]+(r-l+1)*lazy[rt];
     LL cnt=0;
     int mid=(l+r)/2;
         cnt+=Query(ll,rr,lson,lazy[rt]);
     cnt+=Query(ll,rr,rson,lazy[rt]);
    sum[rt]+=(r-l+1)*lazy[rt];
    lazy[rt]=0;
    return cnt;//返回区间的和
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        mem(a,0);mem(b,0);mem(sum,0);mem(lazy,0);
        p=1;
        for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        b[i]=a[i]+b[i-1];
        }
        Build(root);
        for(int i=0;i<m;i++){
            LL x,y,z;
            scanf("%lld%lld%lld",&x,&y,&z);
            if(x==1){
                LL ans=0;
                //if(y!=1)
                    ans=(z-y+1)*Query(y-1,y-1,root,0);
                printf("%lld\n",Query(y,z,root,0)-ans);
            }
            else {
                Update(y,n,z-a[y],root);
                a[y]=z;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/lpeaceminusone/article/details/82622248