题意:动态修改,查询前缀和的前缀和。
一开始下意识树套树,看了看别人长度果断否决了= =,然后没什么思路。
然后我试着化简了一发。。
SSi=∑j=1i(n−j+1)∗a[j]−(n−i)∗sum[j]
简单,两个树状数组搞定。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=2e5+5;
typedef long long ll;
int n,m;
ll t[N],a[N];
ll t1[N],b[N];
char ch[10];
inline int lowbit(int x)
{
return x&(-x);
}
inline void add(int x,ll y)
{
while (x<=n)
{
t[x]+=y;
x+=lowbit(x);
}
}
inline ll ask(int x)
{
ll ans=0;
while (x>0)
{
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
inline void add1(int x,ll y)
{
while (x<=n)
{
t1[x]+=y;
x+=lowbit(x);
}
}
inline ll ask1(int x)
{
ll ans=0;
while (x>0)
{
ans+=t1[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
fo(i,1,n)
{
scanf("%lld",&a[i]);
add(i,a[i]);
b[i]=1ll*(n-i+1)*a[i];
add1(i,b[i]);
}
fo(i,1,m)
{
scanf("%s",ch);
int x,y;
if (ch[0]=='Q')
{
scanf("%d",&x);
printf("%lld\n",ask1(x)-(n-x)*ask(x));
}
else
{
scanf("%d%d",&x,&y);
add(x,-a[x]);
a[x]=y;
add(x,a[x]);
add1(x,-b[x]);
b[x]=1ll*a[x]*(n-x+1);
add1(x,b[x]);
}
}
}