http://poj.org/problem?id=3468
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
1
2
3
4
5
6
710 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
1
2
3
44 55 9 15
Hint
The sums may exceed the range of 32-bit integers.
题目大意:给出n个数和m个操作,Q a b,则输出区间[a,b]的和;Q a b c,则把区间[a,b]的所有元素都加上c。
思路:线段树,因为涉及到区间修改,所以要用到lazy标记。
线段树基本知识:https://blog.csdn.net/xiji333/article/details/87973714
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97#include<iostream> #include<cstdio> #define INF 0x3f3f3f3f typedef long long ll; using namespace std; struct node { ll l,r; ll sum; ll lazy; //lazy标记 }; node tree[100000*4+5]; ll a[100005]; ll n,m; void build(ll i,ll l,ll r) { tree[i].l=l,tree[i].r=r; if(l==r) { tree[i].sum=a[l]; return ; } ll mid=(l+r)>>1; build(i<<1,l,mid); //左子树 build(i<<1|1,mid+1,r); //右子树 tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;//区间和 } void down(ll i)//节点i的标记下传 { tree[i<<1].lazy+=tree[i].lazy; //lazy标记下传 tree[i<<1|1].lazy+=tree[i].lazy; tree[i<<1].sum+=tree[i].lazy*(tree[i<<1].r-tree[i<<1].l+1);//修改值 tree[i<<1|1].sum+=tree[i].lazy*(tree[i<<1|1].r-tree[i<<1|1].l+1); tree[i].lazy=0; } void update(ll i,ll l,ll r,ll v) { if(tree[i].l==l&&tree[i].r==r)//要修改的区间就是当前区间 { tree[i].sum+=(tree[i].r-tree[i].l+1)*v;//修改区间值 tree[i].lazy+=v; //修改lazy标记 return ; } if(tree[i].lazy)//走到这一步说明要用到子节点了 lazy下传 down(i); ll mid=(tree[i].l+tree[i].r)>>1; if(r<=mid)//左半区间 update(i<<1,l,r,v); else if(l>=mid+1)//右半区间 update(i<<1|1,l,r,v); else //左右均有 { update(i<<1,l,mid,v); update(i<<1|1,mid+1,r,v); } tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum; } ll query(ll i,ll l,ll r) { if(tree[i].l==l&&tree[i].r==r)//要查询的区间就是当前区间 return tree[i].sum; if(tree[i].lazy)//要用到子节点 lazy下传 down(i); ll mid=(tree[i].l+tree[i].r)>>1; if(r<=mid)//左半部分 return query(i<<1,l,r); else if(l>=mid+1) //右半部分 return query(i<<1|1,l,r); else //左右均有 return query(i<<1,l,mid)+query(i<<1|1,mid+1,r); } int main() { scanf("%lld %lld",&n,&m); for(ll i=1;i<=n;i++) scanf("%lld",&a[i]); build(1,1,n); char ch; ll t1,t2,t3; for(ll i=0;i<m;i++) { getchar(); ch=getchar(); if(ch=='Q') { scanf("%lld%lld",&t1,&t2); printf("%lldn",query(1,t1,t2)); } else if(ch=='C') { scanf("%lld%lld%lld",&t1,&t2,&t3); update(1,t1,t2,t3); } } return 0; }
最后
以上就是现代樱桃最近收集整理的关于POJ 3468 线段树的全部内容,更多相关POJ内容请搜索靠谱客的其他文章。
发表评论 取消回复