1 条题解
-
0
自动搬运
来自洛谷,原作者为

Leianha
万般皆下品,惟有透彻高搬运于
2025-08-24 22:04:44,当前版本为作者最后更新于2019-09-11 11:42:48,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
树状数组
我们需要求的是 ,即.
暴力求解肯定是不行的,化简式子是OIer的优良传统,所以我们可以考虑化简一下式子。
我们可以考虑一下每一个元素对前前缀合的贡献,第个数被~之间的每一个都计算了一遍,所以它的贡献就是,我们需要求的就是。
我们回到单个元素,根据乘法分配率,我们就得到,
所以$\sum_{i=1}^{k}(k-i+1)\times a_i=\sum_{i=1}^{k}(k+1)\times a_i-\sum_{i=1}^{k}i\times a_i$,
再将提出来之后就得到式子
对于和我们都能够用树状数组来维护,这样我们就能快速的求出答案啦^_^。
再考虑修改,只用这样写
add1(x,y-a[x]);add2(x,(y-a[x])*x);就可以啦~,还是比较简单的。
最后献上我
丑陋的代码#include<algorithm> #include<iostream> #include<cstdio> #define int long long using namespace std; int n,m,x,y; const int N=100010; int ans,len; int a[N],tr1[N<<1],tr2[N<<1]; char s[101]; int read() { char ch;int x=0,f=1; while(!isdigit(ch=getchar())) {(ch=='-')&&(f=-f);} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int lowbit(int x){return x&(-x);} void add1(int pos,int x) { for(int i=pos;i<=(N<<1);i+=lowbit(i))tr1[i]+=x; } void add2(int pos,int x) { for(int i=pos;i<=(N<<1);i+=lowbit(i))tr2[i]+=x; } int ask1(int pos) { int lin=0; for(int i=pos;i;i-=lowbit(i))lin+=tr1[i]; return lin; } int ask2(int pos) { int lin=0; for(int i=pos;i;i-=lowbit(i))lin+=tr2[i]; return lin; } signed main() { cin>>n>>m; for(int i=1;i<=n;++i) { a[i]=read(); add1(i,a[i]);add2(i,a[i]*i); } while(m--) { scanf("%s",s+1); if(s[1]=='Q') { x=read(); ans=((x+1)*ask1(x)-ask2(x)); printf("%lld\n",ans); } else { x=read();y=read(); add1(x,y-a[x]);add2(x,(y-a[x])*x); a[x]=y; } } return 0; }
- 1
信息
- ID
- 3728
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者