我是靠谱客的博主 标致花瓣,这篇文章主要介绍POJ 3468 解题报告,现在分享给大家,希望可以做个参考。

这是按照http://blog.csdn.net/thestoryofsnow/article/details/40942009刷的第4道题,感觉难度已经上来了。看到题目就知道可以用segment tree,于是按照geeksforgeeks的方法做了实现:http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/。然后就是一系列的WA, RE和TLE。主要原因是不熟悉64位int的表示方法。POJ不认识stdint.h,按照报错google了下似乎是windows服务器。RE是之前没有理解对segment tree的最大index的范围。实际上,对于有n个leaf(实际需要保存的数),那么中间节点为n-1个,所以总结点是2n-1个。但是由于segment tree是full binary tree但不是complete binary tree,所以array中有些段是空的,index的最大范围是2 * (N + (N - 1) - 1) + 2 + 1 = 4 * N - 1(这个数应该是取不到的)。所以我最后开了4N的空间。

TLE则是算法的问题了。naive的方法更新的代价很大,实际上要修改涉及到的每个节点,所以比正常的array update开销还大。

参考了

【1】http://blog.sina.com.cn/s/blog_5d34cc430100f0d1.html

【2】http://my.oschina.net/Alexanderzhou/blog/204116

的实现,上面都用的是“延迟更新”的方法,就是把需要更新的值加到delta里面,需要的时候才向下传递。我用的是【1】里面的实现,代码注释写得很好,容易理解。

最后AC了。但显然是擦着边过的,几乎是所有实现中最慢的。我猜和动态分配空间而不是一开始静态分配好及参数传递开销等有关,但主要还是算法实现上面的。目前的实现的好处是自己能够理解,并写出来。AC了也就不想改了。discuss里面提出了很多第一次听说,更别提实现的数据结构,看AC的时间,大神们还有1s多一点过的,程序差距不是一点半点。

Accepted6908K4391MSC++3694B

复制代码
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* ID: thestor1 LANG: C++ TASK: poj3468 */ #include <iostream> #include <fstream> #include <cmath> #include <cstdio> #include <cstring> #include <limits> #include <string> #include <vector> #include <list> #include <set> #include <map> #include <queue> #include <stack> #include <algorithm> #include <cassert> using namespace std; int N; class Segment { public: long long sum, delta; Segment(): sum(0), delta(0) {} }; long long int buildSegmentTree(vector<Segment> &segmentTree, int left, int right, int index, const vector<int> &nums) { // cout << "[debug]left: " << left << ", right: " << right << ", index: " << index << endl; segmentTree[index].delta = 0; if (left == right) { // assert (index < 4 * N - 1); segmentTree[index].sum = nums[left]; return segmentTree[index].sum; } int mid = left + (right - left) / 2; // assert (index < 4 * N - 1); segmentTree[index].sum = buildSegmentTree(segmentTree, left, mid, 2 * index + 1, nums) + buildSegmentTree(segmentTree, mid + 1, right, 2 * index + 2, nums); return segmentTree[index].sum; } long long int getSum(vector<Segment> &segmentTree, int left, int right, const int lindex, const int rindex, int index) { if (lindex <= left && right <= rindex) { return segmentTree[index].sum + segmentTree[index].delta * (right - left + 1); } if (lindex > right || rindex < left) { return 0; } int mid = left + (right - left) / 2; if (segmentTree[index].delta) { // assert (2 * index + 2 < 4 * N - 1); segmentTree[2 * index + 1].delta += segmentTree[index].delta; segmentTree[2 * index + 2].delta += segmentTree[index].delta; segmentTree[index].sum += segmentTree[index].delta * (right - left + 1); segmentTree[index].delta = 0; } return getSum(segmentTree, left, mid, lindex, rindex, 2 * index + 1) + getSum(segmentTree, mid + 1, right, lindex, rindex, 2 * index + 2); } void update(vector<Segment> &segmentTree, int left, int right, const int lindex, const int rindex, int index, const long long int diff) { if (lindex > right || rindex < left) { return; } if (lindex <= left && right <= rindex) { // assert (index < 4 * N - 1); segmentTree[index].delta += diff; return; } int oleft = max(left, lindex), oright = min(right, rindex); // assert (index < 4 * N - 1); segmentTree[index].sum += diff * (oright - oleft + 1); // assert (left != right); int mid = left + (right - left) / 2; update(segmentTree, left, mid, lindex, rindex, 2 * index + 1, diff); update(segmentTree, mid + 1, right, lindex, rindex, 2 * index + 2, diff); } void printSegmentTree(const vector<Segment> &segmentTree) { cout << "segmentTree:" << endl; for (int i = 0; i < segmentTree.size(); ++i) { cout << i << ": " << segmentTree[i].sum << ", "; } cout << endl; } int main() { int Q; cin >> N >> Q; vector<int> nums(N); for (int i = 0; i < N; ++i) { cin >> nums[i]; } // 2 * (N + (N - 1) - 1) + 2 + 1 = 4 * N - 1 vector<Segment> segmentTree(4 * N); buildSegmentTree(segmentTree, 0, N - 1, 0, nums); // printSegmentTree(segmentTree); for (int i = 0; i < Q; ++i) { char type; int lindex, rindex; long long int diff; cin >> type; // cout << "type:" << type << endl; if (type == 'Q') { cin >> lindex >> rindex; // 1-based to 0-based lindex--; rindex--; cout << getSum(segmentTree, 0, N - 1, lindex, rindex, 0) << endl; } else { cin >> lindex >> rindex >> diff; // 1-based to 0-based lindex--; rindex--; update(segmentTree, 0, N - 1, lindex, rindex, 0, diff); } } return 0; }


最后

以上就是标致花瓣最近收集整理的关于POJ 3468 解题报告的全部内容,更多相关POJ内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(80)

评论列表共有 0 条评论

立即
投稿
返回
顶部