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

时间:2024-01-03 10:24:50

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
5

题目链接:

https://nanti.jisuanke.com/t/31460

题目大意:

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

线段树水题。

对该数列建立线段树。每个节点维护两个值sum和tri。sum是区间和,tri是区间三角和(即题目中所要求的和)。适当地改动一下操作,就是一个简单的单点修改,区间查询的线段树问题。

由于是在区域赛预赛中做出来的,还是写个博客纪念一下吧。^_^

#include<cstdio>
#include<cmath> using namespace std; const int maxn=; struct ttree
{
int l,r;
long long sum;
long long tri;
};
ttree tree[maxn*+]; void pushup(int x)
{
if(tree[x].l==tree[x].r)
return;
tree[x].sum=tree[x*].sum+tree[x*+].sum;
tree[x].tri=tree[x*].tri+tree[x*+].tri+
tree[x*].sum*(tree[x*+].r-tree[x*+].l+);
} void build(int x,int l,int r)
{
tree[x].l=l;
tree[x].r=r;
if(l==r)
{
scanf("%lld",&tree[x].sum);
tree[x].tri=tree[x].sum;
}
else
{
int mid=(l+r)/;
build(x*,l,mid);
build(x*+,mid+,r);
pushup(x);
}
} void modify(int x,int pos,int val)
{
if(tree[x].l==tree[x].r)
{
tree[x].sum=tree[x].tri=val;
return;
}
int mid=(tree[x].l+tree[x].r)/;
if(pos<=mid)
modify(x*,pos,val);
else
modify(x*+,pos,val);
pushup(x);
} long long query(int x,int l,int r)
{
if(l<=tree[x].l&&r>=tree[x].r)
return tree[x].sum*(r-tree[x].r)+tree[x].tri;
long long ret=;
int mid=(tree[x].l+tree[x].r)/;
if(l<=mid)
ret+=query(x*,l,r);
if(r>mid)
ret+=query(x*+,l,r);
return ret;
} int main()
{
int n,q;
scanf("%d%d",&n,&q);
build(,,n);
int a,b,c;
while(q--)
{
scanf("%d%d%d",&a,&b,&c);
if(a==)
{
printf("%lld\n",query(,b,c));
}
else
{
modify(,b,c);
}
}
return ;
}