题目链接:https://nanti.jisuanke.com/t/31460
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, 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
要计算题目里类似卷积一样的东西,可以把原数组变成a[i]*=(n-i+1)然后建线段树维护区间和,记为p1(l,r)
再保持数组原样不变,单独维护区间和,记为p2(l,r)
1操作时,直接输出p1(l,r)-p2(l,r)*(n-r+1)
2操作时,更新两个前缀和
#include<bits/stdc++.h>
#include<math.h>
#define MOD 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define LL long long
#define inf 0x3f3f3f3f
#define lan(a,b) memset(a,b,sizeof(a))
#define sqr(x) (x*x)
using namespace std;
#define maxn 100010
struct node
{
int l,r;
LL k;//标记值
LL m;//存储值
};
node tree[2][maxn*4];
LL a[2][maxn];
void build(int n ,int l,int r,int t)
{
tree[t][n].l=l;
tree[t][n].r=r;
if(l==r)
{
tree[t][n].m=a[t][l];//视情况
return;
}
int mid=(l+r)/2;
build(n<<1,l,mid,t);
build(n<<1|1,mid+1,r,t);
tree[t][n].m=tree[t][n<<1].m+tree[t][n<<1|1].m;/看线段树种类
}
void pushup(int n,int t)
{
tree[t][n].m=tree[t][n<<1].m+tree[t][n<<1|1].m;看线段树种类
}
void update(int n,int l,int r,LL c,int t)
{
if(tree[t][n].l==l&&tree[t][n].r==r)
{
tree[t][n].m=c;
return;
}
int mid=(tree[t][n].r+tree[t][n].l)/2;
if(r<=mid)
update(n<<1,l,r,c,t);
else if(l>=mid+1)
update(n<<1|1,l,r,c,t);
else
{
update(n<<1,l,mid,c,t);
update(n<<1|1,mid+1,r,c,t);
}
pushup(n,t);
}
LL query(int n,int l,int r,int t)
{
if(tree[t][n].l==l&&tree[t][n].r==r)
{
return tree[t][n].m;
}
int mid=(tree[t][n].r+tree[t][n].l)/2;
LL res=0;
if(r<=mid)
res+=query(n<<1,l,r,t);
else if(l>=mid+1)
res+=query(n<<1|1,l,r,t);
else
{
res+=query(n<<1,l,mid,t);看线段树种类
res+=query(n<<1|1,mid+1,r,t);看线段树种类
}
return res;
}
int main()
{
LL n,q;
while(~scanf("%lld%lld",&n,&q))
{
lan(tree,0);
lan(a,0);
For(i,1,n)
scanf("%lld",&a[0][i]),a[1][i]=a[0][i];
build(1,1,n,1);
LL tem=n;
For(i,1,n)
{
a[0][i]*=tem;
tem--;
// printf("a%d=%lld\n",i,a[0][i]);
}
build(1,1,n,0);
while(q--)
{
LL op,l,r;
scanf("%lld%lld%lld",&op,&l,&r);
if(op==1)
{
LL ans=0;
ans=query(1,l,r,0)-query(1,l,r,1)*(n-r);
// printf("%lld %lld %lld\n",query(1,l,r,0),query(1,l,r,1),n-r);
printf("%lld\n",ans);
}
else
{
update(1,l,l,r*(n-l+1),0);
update(1,l,l,r,1);
}
}
}
return 0;
}