ACM-ICPC 2018 徐州赛区网络预赛.H--Ryuji doesn't want to study.(线段树维护前缀和)

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:

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

  2. 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)ai .

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, cc represents [ 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 徐州赛区网络预赛
参考的别人的思路,自己想不到、、、、
其实这个可以分解为len个前缀和。设sum(l,r)表示l到r的和,则上式等于:

sum(l,l)+sum(l,l+1)+sum(l,l+2)+…+sum(l,r)

=sum(1,l)+sum(1,l+1)+sum(1,l+2)+…+sum(1,r)-(r-l+1)*sum(1,l-1)

则转化为求前缀和的区间和。然后对单点修改,相当于对要修改的位置i到n所有的前缀和都加增量。

也就转化为线段树查询区间和,区间修改。

区间修改用lazy标志即可。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll tree[maxn<<2];
ll lazy[maxn<<2];
int n,q;
int ip;
ll fo[maxn];
void build(int l,int r,int node)
{
	if(l==r)
	{
		tree[node]=fo[ip++];
		return;
	}
	ll m=(l+r)>>1;
	build(l,m,node*2);
	build(m+1,r,node*2+1);
	tree[node]=tree[node*2]+tree[node*2+1];
}
ll query(int L,int R,int l,int r,int node,ll z)
{
	lazy[node]+=z;
	if(L>r||R<l)
	{
		return 0;
	}
	if (L <= l && r <= R) {
        return tree[node]+lazy[node]*(r-l+1);
    }
    ll m=(l+r)>>1;
    ll ret=0;
    ret+=query(L,R,l,m,node*2,lazy[node]);
    ret+=query(L,R,m+1,r,node*2+1,lazy[node]);
    tree[node]=lazy[node]*(r-l+1);
    lazy[node]=0;
    return ret;
}
void update(int L,int R,int add,int l,int r,int node)
{
	if(l==r)
	{
		tree[node]+=add;
		return;
	}
	if(L<=l&&R>=r)
	{
		lazy[node]+=add;
	}
	ll m=(l+r)>>1;
	if(L<=m)
	{
	update(L,R,add,l,m,node*2);
}
if(R>m)
{
	update(L,R,add,m+1,r,node*2+1);
 }
 tree[node]=tree[node*2]+tree[node*2+1];
}
int main()
{
	int co[maxn];
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        scanf("%d",&co[i]);
        fo[i]=co[i]+fo[i-1];
    }
    ip=1;
    build(1,n,1);
    int l,r,len,v,d,flag;
    while(q--)
    {
        scanf("%d",&flag);
        if(flag==1){
            scanf("%d%d",&l,&r);
            len=r-l+1;
            printf("%lld\n",query(l,r,1,n,1,0)-len*query(l-1,l-1,1,n,1,0));
        }
        else{
            scanf("%d%d",&d,&v);
            update(d,n,v-co[d],1,n,1);
            co[d]=v;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值