题目链接:点击打开链接
题目大意:
多组数据,单点更新,区间查询
思路:
裸的线段树,手打了一遍练练感觉,但是问题还是挺多的;
总结一下,
(1)单点更新时,以mid作为基准,如果mid>=id查左边的,如果mid<id查右边的;
(2)build的时候,要理清思路,先给树的左右节点位置赋值;
(3)查询时,应该以当前树的L和R算出mid,设查询区间为(l,r),如果l<=mid,则查询左子树,否则查右子树,最后一步才返回ans;
(4)当读到End的时候,是没有输入的!!!这一点卡了很久!!!、
#include<bits/stdc++.h> using namespace std; const int maxn = 50005; typedef long long ll; ll t,n,a[maxn]; struct node{ ll l,r; ll sum; ll lazy; void update(ll x) { sum += (r-l+1)*x; lazy += x; } }tree[maxn*4]; void push_up(int x) { tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum; } void push_down(int x) { if(tree[x].lazy) { int lazyval = tree[x].lazy; tree[x<<1].update(lazyval); tree[x<<1|1].update(lazyval); tree[x].lazy = 0; } } void build(int x,int l,int r) { tree[x].l = l; tree[x].r = r; tree[x].sum = tree[x].lazy = 0; if(l==r) { tree[x].sum = a[l]; return; } int mid = (l+r)/2; build(x<<1,l,mid); build(x<<1|1,mid+1,r); push_up(x); } void update(int x,int id,int val) { int l = tree[x].l; int r = tree[x].r; // cout<<l<<" "<<r<<" "<<tree[x].sum<<endl; if(l==id&&r==id) { tree[x].update(val); return; } int mid = (l+r)/2; push_down(x); if(id<=mid) update(x<<1,id,val); if(id>mid) update(x<<1|1,id,val); push_up(x); } long long query(int x,int l,int r) { ll ans = 0; int L = tree[x].l; int R = tree[x].r; //cout<<L<<" "<<R<<" "<<tree[x].sum<<endl; if(l<=L&&r>=R) ans += tree[x].sum; else { int mid = (L+R)/2; if(l<=mid) ans += query(x<<1,l,r); if(r>mid) ans += query(x<<1|1,l,r); } return ans; } int main() { //freopen("d://test.txt","r",stdin); cin>>t; int cnt = 1; while(cnt<=t) { cout<<"Case "<<cnt++<<":"<<endl; cin>>n; // cout<<n<<endl; memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); build(1,1,n); string s; while(cin>>s) { int x,y; if(s[0]=='A') { scanf("%d%d",&x,&y); update(1,x,y); } else if(s[0]=='S') { scanf("%d%d",&x,&y); update(1,x,-y); } else if(s[0]=='Q') { scanf("%d%d",&x,&y); cout<<query(1,x,y)<<endl; } else if(s[0]=='E') { break; } } } return 0; }