正式比赛线段树第一题。
很裸的线段树,维护一个区间和及答案,答案由左右两边的答案及左边的区间和乘上右边的长度可得。
求答案的时候要线段树合并。
//#define test #include<bits/stdc++.h> using namespace std; const int Nmax=1e5+7; typedef long long ll; ll num[Nmax]; int op,l,r,n,q,pos,now_root; struct Node { ll l; ll r; ll data; ll sum; } tree[Nmax<<3]; void push_up(int root,int l,int r) { tree[root].l=tree[l].l,tree[root].r=tree[r].r; tree[root].sum=tree[l].sum+tree[r].sum; tree[root].data=tree[l].sum*(tree[r].r-tree[r].l+1)+tree[l].data+tree[r].data; } void build(int root,int l,int r) { tree[root].l=l; tree[root].r=r; if(l==r) { tree[root].data=tree[root].sum=num[l]; return; } if(l<r) { int mid=(l+r)>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); push_up(root,root<<1,root<<1|1); } } void update(int root,int l,int r,int data) { if(l==r) { tree[root].data=tree[root].sum=data; return ; } int mid=(l+r)>>1; if(pos<=mid) update(root<<1,l,mid,data); else update(root<<1|1,mid+1,r,data); push_up(root,root<<1,root<<1|1); } int query(int root,int l,int r,int L,int R) { if(L==l && R==r) return root; int mid=(L+R)>>1; int ans=0; if(mid<l) return query(root<<1|1,l,r,mid+1,R); else if(mid>=r) return query(root<<1,l,r,L,mid); else { int ls=query(root<<1,l,mid,L,mid),rs=query(root<<1|1,mid+1,r,mid+1,R); push_up(++now_root,ls,rs); return now_root; } } int main() { //freopen("1.in","r",stdin); scanf("%d%d",&n,&q); for(int i=1; i<=n; i++) scanf("%lld",&num[i]); build(1,1,n); while(q--) { scanf("%d",&op); if(op==1) { scanf("%d%d",&l,&r); now_root=Nmax<<2+1; printf("%lld\n",tree[query(1,l,r,1,n)].data); } else { ll data; scanf("%d%lld",&pos,&data); update(1,1,n,data); } } return 0; }