BZOJ3155
-
题目
-
分析
要求的 S n S_n Sn :
S n = ∑ i = 1 n ∑ j = 1 i a j S n = ∑ i = 1 n ( n − i + 1 ) a i 容 斥 一 下 : S n = ( n + 1 ) ∑ i = 1 n a i − ∑ i = 1 n i × a i \begin{aligned} &S_n = \sum_{i = 1}^{n}\sum_{j = 1}^{i}a_j \\ &S_n = \sum_{i = 1}^{n} (n - i + 1)a_i \\ &容斥一下:\\ &S_n = (n + 1)\sum_{i = 1}^{n}a_i - \sum_{i = 1}^{n}i\times a_i \end{aligned} Sn=i=1∑nj=1∑iajSn=i=1∑n(n−i+1)ai容斥一下:Sn=(n+1)i=1∑nai−i=1∑ni×ai
开线段树或者树状数组维护两个前缀和: a i a_i ai 和 i × a i i \times a_i i×ai 即可。。注意 l o n g   l o n g long \, long longlong 别炸 i n t int int 了。
-
代码
const int N = 1e5 + 5; int a[N]; struct stree { int l; int r; ll suma; ll sumi; } tree[N << 2]; void pushup(int rt) { tree[rt].suma = tree[rt << 1].suma + tree[rt << 1 | 1].suma; tree[rt].sumi = tree[rt << 1].sumi + tree[rt << 1 | 1].sumi; } void build(int rt, int l, int r) { tree[rt].l = l; tree[rt].r = r; if (l == r) { tree[rt].suma = a[l]; tree[rt].sumi = (ll)a[l] * l; return ; } int mid = (l + r) >> 1; build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r); pushup(rt); } void updatea(int rt, int x, ll val) { int l = tree[rt].l; int r = tree[rt].r; if (l == r) { tree[rt].suma = val; return ; } int mid = (l + r) >> 1; if (x <= mid) updatea(rt << 1, x,val); else updatea(rt << 1 | 1, x,val); pushup(rt); } void updatei(int rt, int x, ll val) { int l = tree[rt].l; int r = tree[rt].r; if (l == r) { tree[rt].sumi = val; return ; } int mid = (l + r) >> 1; if (x <= mid) updatei(rt << 1, x,val); else updatei(rt << 1 | 1, x,val); pushup(rt); } ll querya(int rt, int L, int R) { int l = tree[rt].l; int r = tree[rt].r; if (L <= l && r <= R) return tree[rt].suma; int mid = (l + r) >> 1; ll ans = 0; if (L <= mid) ans += querya(rt << 1, L, R); if (R > mid) ans += querya(rt << 1 | 1, L, R); return ans ; } ll queryi(int rt, int L, int R) { int l = tree[rt].l; int r = tree[rt].r; if (L <= l && r <= R) return tree[rt].sumi; int mid = (l + r) >> 1; ll ans = 0; if (L <= mid) ans += queryi(rt << 1, L, R); if (R > mid) ans += queryi(rt << 1 | 1, L, R); return ans ; } int main () { //freopen("4.in", "r", stdin); //freopen("test.out", "w", stdout); int n, m; read(n); read(m); for (int i = 1; i <= n; i++) read(a[i]); build(1, 1, n); while (m--) { char s[20]; scanf("%s", &s); if (s[0] == 'Q') { ll x; read(x); ll ans = (ll)(x + 1) * querya(1, 1, x) - queryi(1, 1, x); printf("%lld\n", ans); } else { ll pos, x; read(pos); read(x); updatea(1, pos, x); updatei(1, pos, x * pos); } } return 0 ; }
-
题型
线段树 o r or or 树状数组