BZOJ3155

BZOJ3155
  • 题目

    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=1nj=1iajSn=i=1n(ni+1)aiSn=(n+1)i=1naii=1ni×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 树状数组

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值