1. 程式人生 > >ACM-ICPC 2018 徐州賽區網絡預賽 H Ryuji doesn't want to study (樹狀數組差分)

ACM-ICPC 2018 徐州賽區網絡預賽 H Ryuji doesn't want to study (樹狀數組差分)

() clas targe anti icpc -- nbsp nan ant

https://nanti.jisuanke.com/t/31460

題意

兩個操作。1:查詢區間[l,r]的和,設長度為L=r-l+1, sum=a[l]*L+a[l+1]*(L-1)+...+a[r]。2:將第a個位置修改為b。

分析

變形一下,sum=a[l]*(r-l+1)+a[l+1]*(r-(l+1)-1)+...+a[r](r-r+1)=(r+1)*a[l]-a[l]*l。因此,可維護兩個樹狀數組計算。至於更新操作,實質就是看變化前後的差值,變大就相當與加上差值,否則就是減。註意用longlong

#include<bits/stdc++.h>
const int
maxn = 1e5 + 10; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; typedef long long ll; ll c1[maxn],c2[maxn]; int a[maxn]; int lb(int x){ return x&-x; } void add(ll c[],int x,ll d){ while(x<maxn){ c[x]+=d; x+=lb(x); } } ll sum(ll c[],int x){ ll res
=0; while(x){ res+=c[x]; x-=lb(x); } return res; } ll query(int l,int r){ return (r+1)*(sum(c1,r)-sum(c1,l-1))-(sum(c2,r)-sum(c2,l-1)); } int main(){ int n,q; int op,x,y; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { scanf(
"%d",&x); add(c1,i,x); add(c2,i,1ll*i*x); a[i]=x; } while(q--){ scanf("%d%d%d",&op,&x,&y); if(op==1){ printf("%lld\n",query(x,y)); }else{ add(c1,x,y-a[x]); add(c2,x,1ll*x*(y-a[x])); a[x]=y; } } return 0; }

ACM-ICPC 2018 徐州賽區網絡預賽 H Ryuji doesn't want to study (樹狀數組差分)