HDU 1166 敌兵布阵 (线段树 单点更新)
线段树掌握的很差,打算从头从最简单的开始刷一波, 嗯。。就从这个题开始吧!
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <cstdlib> 6 #include <algorithm> 7 const int maxn = 50000+10; 8 using namespace std; 9 int a[maxn], n; 10 struct line 11 { 12 int l, r, val; 13 }tr[maxn<<2]; 14 15 void build(int o, int l, int r) 16 { 17 tr[o].l = l; tr[o].r = r; 18 if(l == r) 19 { 20 tr[o].val = a[l]; 21 return; 22 } 23 int mid = (l+r)>>1; 24 build(2*o, l, mid); 25 build(2*o+1, mid+1, r); 26 tr[o].val = tr[2*o].val+tr[2*o+1].val; 27 } 28 int query(int o, int l, int r) 29 { 30 if(tr[o].l==l && tr[o].r==r) 31 return tr[o].val; 32 int mid = (tr[o].l+tr[o].r)>>1; 33 if(r <= mid) query(2*o, l, r); 34 else if(l > mid) query(2*o+1, l, r); 35 else 36 return (query(2*o, l, mid)+query(2*o+1, mid+1, r)); 37 } 38 void update(int o, int p, int add) 39 { 40 if(tr[o].l==tr[o].r&&tr[o].l==p) 41 { 42 tr[o].val += add; 43 return; 44 } 45 int mid = (tr[o].l+tr[o].r)>>1; 46 if(p<=mid) update(2*o, p, add); 47 else update(2*o+1, p, add); 48 tr[o].val = tr[2*o].val+tr[2*o+1].val; 49 } 50 int main() 51 { 52 int t, i, ca = 1; 53 int p, add, l, r; 54 char s[20]; 55 scanf("%d", &t); 56 while(t--) 57 { 58 scanf("%d", &n); 59 for(i = 1; i <= n; i++) 60 scanf("%d", &a[i]); 61 printf("Case %d:\n", ca++); 62 63 build(1, 1, n); 64 while(~scanf("%s", s)) 65 { 66 if(strcmp(s, "End")==0) break; 67 if(s[0]=='Q') 68 { 69 scanf("%d%d", &l, &r); 70 printf("%d\n", query(1, l, r)); 71 } 72 if(s[0]=='A') 73 { 74 scanf("%d%d", &p, &add); 75 update(1, p, add); 76 } 77 if(s[0]=='S') 78 { 79 scanf("%d%d", &p, &add); 80 update(1, p, -add); 81 } 82 } 83 } 84 return 0; 85 }
注释的代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <cstdlib> 6 #include <algorithm> 7 const int maxn = 50000+10; 8 using namespace std; 9 int a[maxn], n; 10 struct line 11 { 12 int l, r, val; //val表示该区间的和 13 }tr[maxn<<2]; 14 15 void build(int o, int l, int r) //o代表当前节点编号 16 { 17 tr[o].l = l; tr[o].r = r; 18 if(l == r) 19 { 20 tr[o].val = a[l]; 21 return; 22 } 23 int mid = (l+r)>>1; 24 build(2*o, l, mid); 25 build(2*o+1, mid+1, r); 26 tr[o].val = tr[2*o].val+tr[2*o+1].val; //建树把值从下往上加起来 27 } 28 int query(int o, int l, int r) //求l到r的和 29 { 30 if(tr[o].l==l && tr[o].r==r) //节点的区间吻合返回 31 return tr[o].val; 32 int mid = (tr[o].l+tr[o].r)>>1; 33 if(r <= mid) query(2*o, l, r); 34 else if(l > mid) query(2*o+1, l, r); 35 else 36 return (query(2*o, l, mid)+query(2*o+1, mid+1, r)); //横跨了区间 37 } 38 void update(int o, int p, int add) //对p节点增加add 39 { 40 if(tr[o].l==tr[o].r&&tr[o].l==p) 41 { 42 tr[o].val += add; 43 return; 44 } 45 int mid = (tr[o].l+tr[o].r)>>1; 46 if(p<=mid) update(2*o, p, add); 47 else update(2*o+1, p, add); 48 tr[o].val = tr[2*o].val+tr[2*o+1].val; //找到值以后的更新 49 } 50 int main() 51 { 52 int t, i, ca = 1; 53 int p, add, l, r; 54 char s[20]; 55 scanf("%d", &t); 56 while(t--) 57 { 58 scanf("%d", &n); 59 for(i = 1; i <= n; i++) 60 scanf("%d", &a[i]); 61 printf("Case %d:\n", ca++); 62 63 build(1, 1, n); 64 while(~scanf("%s", s)) 65 { 66 if(strcmp(s, "End")==0) break; 67 if(s[0]=='Q') 68 { 69 scanf("%d%d", &l, &r); 70 printf("%d\n", query(1, l, r)); 71 } 72 if(s[0]=='A') 73 { 74 scanf("%d%d", &p, &add); 75 update(1, p, add); 76 } 77 if(s[0]=='S') 78 { 79 scanf("%d%d", &p, &add); 80 update(1, p, -add); 81 } 82 } 83 } 84 return 0; 85 }