树状数组维护区间加减与查询
NOIP ,发条题解增加rp;
树状数组维护区间和。
令 原数组为a i a1 i为 ai 到 an的共同增量,
那么 我们要求区间和 等价于求 1到x的和 (可以ask r-ask(l-1));
ask x =a1+a2+..ax+x*a1 1+(x-1)*a1 2+..a1 x
=a1+a2+..ax+(x+1)*(a1 1+a1 2+a1 3+...a1 x)-1*a1 1-2*a1 2-3*a1 3...x*a1 x
那么我们维护 a1 和 i*a1 的数组即可
下附代码
#include<bits/stdc++.h> #define sight(c) ('0'<=c&&c<='9') #define LL long long #define gc getchar #define getchar nc #define L(x) (x&-x) #define N 100007 using namespace std; LL a[N],a1[N],a2[N],x,y,k,op,n,m; inline char nc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } inline void read(LL &x){ static char c; for(c=gc();!sight(c);c=gc()); for(x=0;sight(c);c=gc()) x=x*10+c-48; } void write(LL x){if (x<10) {putchar('0'+x);return;}write(x/10); putchar('0'+x%10);} inline void change(LL *A,int x,int dla) {for (;x<N;x+=L(x)) A[x]+=dla;} inline LL add(LL *A,int x){LL O=0;for(;x;x-=L(x)) O+=A[x];return O;} inline LL ask(int r){return a[r]+(r+1)*add(a1,r)-add(a2,r);} int main () { read(n); read(m); for (int i=1;i<=n;i++) read(x),a[i]=a[i-1]+x; while (m--) { read(op); if (op&1) { read(x); read(y); read(k); change(a1,x,k); change(a1,y+1,-k); change(a2,x,k*x); change(a2,y+1,-k*(y+1)); } else { read(x); read(y); write(ask(y)-ask(x-1)); putchar('\n'); } } return 0; }