版权声明:转载请注明出处 https://blog.csdn.net/jay__bryant/article/details/82563391
题意:有n本书和q次询问(n,q<=1e5),给定n本书的知识值ai。询问1:i,j,区间[i, j]的价值。询问2:a, b,将第a本书的知识值改为b。PS:[i, j]的价值计算,a[i]xL+a[i+1]x(L-1)+…+a[j-1]x2+a[j],L==j-i+1。
线段树维护三个东西
sum[]:单纯的知识值的和
ans[]:价值
len[]:区间长度
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
ll sum[maxn<<2];
ll ans[maxn<<2];
ll len[maxn<<2];
int Len;
void pushup(int rt)
{
ans[rt] = ans[rt<<1]+ans[rt<<1|1]+sum[rt<<1]*len[rt<<1|1];
len[rt] = len[rt<<1]+len[rt<<1|1];
sum[rt] = sum[rt<<1]+sum[rt<<1|1];
}
void build(int l, int r, int rt)
{
if(l == r)
{
scanf("%lld", &sum[rt]);
len[rt] = 1;
ans[rt] = sum[rt];
return;
}
int mid = (l + r)>>1;
build(l, mid, rt<<1);
build(mid + 1, r, rt<<1|1);
pushup(rt);
}
ll query(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R)
{
int tmp = Len;
Len -= len[rt];
return ans[rt]+sum[rt]*(tmp-len[rt]);
}
int mid = (l + r)>>1;
ll ret = 0;
if(L <= mid)
ret += query(L, R, l, mid, rt<<1);
if(R >= mid + 1)
ret += query(L, R, mid + 1, r, rt<<1|1);
return ret;
}
void update(int p, ll th, int l, int r, int rt)
{
if(l == r)
{
sum[rt] = th;
ans[rt] = th;
return;
}
int mid = (l + r)>>1;
if(p <= mid)
update(p, th, l, mid, rt<<1);
else
update(p, th, mid + 1, r, rt<<1|1);
pushup(rt);
}
int main()
{
int n, m;
while(~scanf("%d %d", &n, &m))
{
build(1, n, 1);
while(m--)
{
int op;
scanf("%d", &op);
if(op == 1)
{
int a, b;
scanf("%d %d", &a, &b);
Len = b-a+1;
printf("%lld\n", query(a, b, 1, n, 1));
}
else
{
int a;
ll b;
scanf("%d %lld", &a, &b);
update(a, b, 1, n, 1);
}
}
}
return 0;
}