ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study 【线段树】

  •  1000ms
  •  262144K

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].

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

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

Now Ryuji has q questions, you should answer him:

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

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

Input

First line contains two integers nn and q (n, q≤100000).

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

Then in next q line each line contains three integers a, b, c, if a=1, it means question type is 1, and b, ccrepresents [ l , r ]. if a=2 , it means question type is 2 , and b, c means Ryuji changes the bth book' knowledge to c

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 徐州赛区网络预赛

问题描述

给你一个数列a[1..n],多次求对于[i..j]区间,a[i]*L+a[i+1]*(L-1)+...+a[j]*1,其中L是区间长度(j-i+1)。或者改变某个a[i]的值。

思路

线段树求解

AC的C++代码

#include<iostream>
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;
typedef long long ll;
const int N=100010;
ll sum[N<<2],ans[N<<2],a[N];

void pushup(int l,int r,int rt)
{
	int m=(l+r)>>1;
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
	ans[rt]=ans[rt<<1]+ans[rt<<1|1]+(r-m)*sum[rt<<1];
}
void build(int l,int r,int rt)
{
	if(l==r){
		sum[rt]=a[l];
		ans[rt]=a[l];
		return;
	}
	int m=(l+r)>>1;
	build(ls);
	build(rs);
	pushup(l,r,rt);
}

void update(int L,ll C,int l,int r,int rt)
{
	if(l==r){
		sum[rt]=C;
		ans[rt]=C;
		return;
	}
	int m=(l+r)>>1;
	if(L<=m)
	  update(L,C,ls);
	else
	  update(L,C,rs);
	pushup(l,r,rt);
}

ll query(int L,int R,int l,int r,int rt)
{
	if(L<=l&&r<=R)
	  return ans[rt]+sum[rt]*(R-r);
	int m=(l+r)>>1;
	ll res=0;
	if(L<=m)
	  res+=query(L,R,ls);
	if(R>=m+1)
	  res+=query(L,R,rs);
	return res;
} 

int main()
{
	ll n,q,A,B,C;
	scanf("%lld%lld",&n,&q);
	for(int i=1;i<=n;i++)
	  scanf("%lld",&a[i]);
	build(1,n,1);
	while(q--){
		scanf("%lld%lld%lld",&A,&B,&C);
		if(A==1)
		  printf("%lld\n",query(B,C,1,n,1));
		else
		  update(B,C,1,n,1);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SongBai1997/article/details/82832941