版权声明:本文为博主原创文章,转载请预先通知博主(〃'▽'〃)。 https://blog.csdn.net/m0_37624640/article/details/82632700
做法:
- 我们知道我们想要的答案的式子中,相邻两项的系数差1,所以我们构造出类似这样的情况
- 如下图所示
n*a1 (n-1)*a2 (n-2)*a3 (n-3)*a4 (n-4)*a5 (n-5)*a6 (n-6)*a7 (n-7)*a8
- 比如n = 8
- 想查询[2,4]
- 答案ans = (4-2+1)*a2+(4-2)*a3+(4-2-1)*a4 = 3*a2+2*a3+a4
- 而构造的是 sum = 7*a2+6*a3+5*a4 他们之间超差了4倍的(a2+a3+a4)
- 这时候我们发现了,我们可以使用树状数组的区间查询查找a2+a3+a4。我们只需要在求出sum,就可以
- 通过作差求得ans。
- 那么,怎么求sum呢?
- 我们发现我们本身构造的这个式子,也可以通过树状数组维护,因为是可维护的!
- 所以我们需要开三个数组,原数组,差分数组,sum数组( (n-i+1)*ai )
- 然后区间维护,区间修改来维护就可以啦~~
AC代码:
#include<bits/stdc++.h>
#define IO ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x) push_back(x)
#define sz(x) (int)(x).size()
#define sc(x) scanf("%d",&x)
#define pr(x) printf("%d\n",x)
#define abs(x) ((x)<0 ? -(x) : x)
#define all(x) x.begin(),x.end()
#define mk(x,y) make_pair(x,y)
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const double PI = 4*atan(1.0);
const int maxm = 1e8+5;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
ll c1[maxn];
ll c2[maxn];
ll sum[maxn];
ll n,m;
inline ll read()
{
char x;
bool flag = false;
while(x = getchar(),x<'0' || x>'9') if(x == '-') flag = true;
ll u = x-'0';
while(x = getchar(),x>='0' && x<='9') u = (u<<3)+(u<<1)+x-'0';
if(flag) u = -u;
return u;
}
inline ll lowbit(ll x) {return x&(-x);}
void update(ll *tree,ll x,ll val)
{
for(ll i=x;i<=n;i+=lowbit(i)) tree[i]+=val;
}
ll getSum(ll *tree,ll x)
{
ll res = 0;
for(ll i=x;i;i-=lowbit(i)) res+=tree[i];
return res;
}
ll query(ll x)
{
ll ans1 = x*getSum(c1,x);
ll ans2 = getSum(c2,x);
return ans1-ans2;
}
ll range_query(ll l,ll r)
{
return query(r)-query(l-1);
}
int main()
{
#ifdef LOCAL_FILE
freopen("in.txt","r",stdin);
#endif // LOCAL_FILE
n = read();m = read();
ll l = 0,r;
for(ll i=1;i<=n;i++)
{
r = read();
update(c1,i,r-l);
update(c2,i,(i-1)*(r-l));
update(sum,i,(n-i+1)*r);
l = r;
}
while(m--)
{
int c;sc(c);
if(c == 1){
ll l,r;
l = read(); r = read();
ll k = r-l+1;
ll k1 = n-l+1;
ll ans = range_query(l,r);
ll res = getSum(sum,r)-getSum(sum,l-1);
printf("%lld\n",res-(k1-k)*ans);
}
else{
ll pos,nw;
pos = read();nw = read();
ll change = nw-getSum(c1,pos);
update(c1,pos,change);
update(c1,pos+1,-change);
update(c2,pos,(pos-1)*change);
update(c2,pos+1,-change*(pos));
update(sum,pos,(n-pos+1)*change);
}
}
return 0;
}