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 <cstdio> #include <algorithm> using namespace std; int f[50011]; int n; //总阵地数 void add(int x,int y) //第x个阵地添加y个人 { while (x <= n) { f[x] += y; x += x & (-x); //消除前面的0 } } int cal(int x,int y) //x到y的人数(x < y) { x--; int sum1,sum2; sum1 = sum2 = 0; while (x) { sum1 += f[x]; x -= x & (-x); } while (y) { sum2 += f[y]; y -= y & (-y); } return sum2 - sum1; } int main() { int u; int num = 1; char op[8]; scanf ("%d",&u); while (u--) { printf ("Case %d:\n",num++); scanf ("%d",&n); for (int i = 1 ; i <= n ; i++) f[i] = 0; for (int i = 1 ; i <= n ; i++) { int t; scanf ("%d",&t); add (i,t); } int ans; while (scanf ("%s",op)) { if (op[0] == 'E') break; int x,y; scanf ("%d %d",&x,&y); if (op[0] == 'Q') { ans = cal(x,y); printf ("%d\n",ans); } else if (op[0] == 'A') add (x,y); else add (x,-y); } } return 0; }
下面是学会线段树之后的代码,时间上要长一点,贴图比较一下:
代码如下:
#include <stdio.h> #define MAX 50000 struct TREE { int sum; int l,r; }tree[MAX<<2]; void PushUp(int o) { tree[o].sum = tree[o << 1].sum + tree[o << 1 | 1].sum; } void Build(int o,int l,int r) { tree[o].l = l; tree[o].r = r; if (l == r) { scanf ("%d",&tree[o].sum); return; } int mid = (l + r) >> 1; Build(o << 1 , l , mid); Build(o << 1 | 1 , mid + 1 , r); PushUp(o); } void UpDate(int o,int x,int y) //x加y(y可能为负数) //单点更新 { if (tree[o].l == tree[o].r) { tree[o].sum += y; return; } int mid = (tree[o].l + tree[o].r) >> 1; if (mid >= x) UpDate (o << 1 , x , y); else UpDate (o << 1 | 1 , x , y); PushUp(o); } int Query(int o,int l,int r) { if (tree[o].l == l && tree[o].r == r) return tree[o].sum; int mid = (tree[o].l + tree[o].r) >> 1; if (mid >= r) return Query (o << 1 , l , r); else if (mid < l) return Query (o << 1 | 1 , l , r); else return (Query (o << 1 , l , mid) + Query (o << 1 | 1 , mid + 1 , r)); } int main() { int u; int n; int num = 1; scanf ("%d",&u); while (u--) { scanf ("%d",&n); Build (1,1,n); char op[8]; printf ("Case %d:\n",num++); while (scanf ("%s",op)) { if (op[0] == 'E') break; else if (op[0] == 'A') { int x,y; scanf ("%d %d",&x,&y); UpDate (1,x,y); } else if (op[0] == 'S') { int x,y; scanf ("%d %d",&x,&y); UpDate (1,x,-y); } else { int x,y; scanf ("%d %d",&x,&y); printf ("%d\n",Query(1,x,y)); } } } return 0; }