1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End
Case 1: 6 33 59
線段樹基礎題,開始刷線段樹的題啦,理解線段樹的這種數據結構,樹結構儲存這個線段;
單點更新;主要是掌握裡面的建樹,查詢,更新,操作;都是通過遞歸實現;
下面是代碼:
#include#include using namespace std; const int maxn=50050; struct node//線段樹結構 { int l,r,val; }t[maxn*3]; int a[maxn]; void build(int root,int l,int r)//建樹 { int m; t[root].l=l; t[root].r=r; if(l==r) { t[root].val=a[l]; return ; } m=(l+r)/2; build(root*2,l,m); build(root*2+1,m+1,r); t[root].val=t[root*2].val+t[root*2+1].val; } int query(int root,int l,int r)//查詢,遞歸查詢需要的值 { int m; if(t[root].l==l && t[root].r==r) return t[root].val; m=(t[root].l+t[root].r)/2; if(r<=m) return query(root*2,l,r); else if(l>m) return query(root*2+1,l,r); else return query(root*2,l,m)+query(root*2+1,m+1,r); } void update(int root,int id,int num)//更新 { if(t[root].l==t[root].r) { t[root].val+=num;//更新這個點的值 return ; } else { t[root].val+=num; if(id<=t[root*2].r) update(root*2,id,num); else update(root*2+1,id,num); } } int main() { int t,n,i,id,num; char s[10]; int k=1; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); printf("Case %d:\n",k++); while(1) { scanf("%s",s); if(strcmp(s,"End")==0) break; scanf("%d%d",&id,&num); if(strcmp(s,"Query")==0) { printf("%d\n",query(1,id,num)); } if(strcmp(s,"Add")==0) { update(1,id,num); } if(strcmp(s,"Sub")==0) { update(1,id,-num); } } } return 0; }