http://acm.hdu.edu.cn/showproblem.php?pid=1166
这是一道线段树的基础入门题,题目中的所有跟新操作都是对点进行的,也即无需任何lazy标记传递信息。由于是对点进行的操作,我们在建树的时候应该将数建成点树,即 build(2*i,l,mid); build(2*i+1,mid+1,r); 后面将会有需要段树的题目,待续。 这题唯一的技巧应该就是查找了,我们在对某点进行跟新之后,可以采用之下而上的DP方式,跟新每一段中的人数信息,这样就可以为查找节约很多时间
View Code
1 #include<iostream>
2 #include<string>
3 using namespace std;
4
5 struct node
6 {
7 int l;
8 int r;
9 int sum;
10 };
11
12 node tree[250000];
13 int n;
14 int num[50001];
15
16 void build(int i,int l,int r)
17 {
18 tree[i].l=l;
19 tree[i].r=r;
20 if(l==r)
21 {
22 tree[i].sum=num[l];
23 return;
24 }
25 int mid=(l+r)/2;
26 build(2*i,l,mid);
27 build(2*i+1,mid+1,r);
28 tree[i].sum=tree[2*i].sum+tree[2*i+1].sum; //从下向上返回跟新,为查找节约时间
29 }
30
31 void updata(int i,int l,int r,int w)
32 {
33 if(tree[i].l>r || tree[i].r<l)
34 return;
35 if(tree[i].l>=l && tree[i].r<=r)
36 {
37 tree[i].sum+=w;
38 return;
39 }
40 updata(2*i,l,r,w);
41 updata(2*i+1,l,r,w);
42 tree[i].sum=tree[2*i].sum+tree[2*i+1].sum; //从下向上返回跟新,为查找节约时间
43 }
44
45 int ans;
46 void find(int i,int l,int r)
47 {
48 if(tree[i].l>r || tree[i].r<l)
49 return;
50 if(tree[i].l>=l && tree[i].r<=r)
51 {
52 ans+=tree[i].sum;
53 return;
54 }
55 find(2*i,l,r);
56 find(2*i+1,l,r);
57 }
58
59 int main()
60 {
61 int cas,i,a,b,o=1;
62 char str[10];
63 freopen("in.txt","r",stdin);
64 scanf("%d",&cas);
65 while(cas--)
66 {
67 scanf("%d",&n);
68 for(i=1;i<=n;i++)
69 scanf("%d",&num[i]);
70 build(1,1,n);
71 printf("Case %d:\n",o++);
72 while(1)
73 {
74 scanf("%s",str);
75 if(str[0]=='E')
76 break;
77 scanf("%d%d",&a,&b);
78 if(str[0]=='S')
79 {
80 updata(1,a,a,-b);
81 }
82 else if(str[0]=='A')
83 {
84 updata(1,a,a,b);
85 }
86 else
87 {
88 ans=0;
89 find(1,a,b);
90 printf("%d\n",ans);
91 }
92 }
93 }
94 return 0;
95 }