[题解]线段树专题测试2017.1.21
Posted 阿波罗2003
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解]线段树专题测试2017.1.21相关的知识,希望对你有一定的参考价值。
很单纯的一道线段树题。稍微改一下pushDown()就行了。
Code(线段树模板竟然没超100行)
1 #include<iostream> 2 #include<sstream> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<cctype> 8 #include<queue> 9 #include<set> 10 #include<map> 11 #include<stack> 12 #include<vector> 13 #include<algorithm> 14 using namespace std; 15 typedef bool boolean; 16 #ifdef WIN32 17 #define AUTO "%I64d" 18 #else 19 #define AUTO "%lld" 20 #endif 21 #define smin(a, b) (a) = min((a), (b)) 22 #define smax(a, b) (a) = max((a), (b)) 23 template<typename T> 24 inline void readInteger(T& u){ 25 char x; 26 int aFlag = 1; 27 while(!isdigit((x = getchar())) && x != \'-\'); 28 if(x == \'-\'){ 29 aFlag = -1; 30 x = getchar(); 31 } 32 for(u = x - \'0\'; isdigit((x = getchar())); u = u * 10 + x - \'0\'); 33 ungetc(x, stdin); 34 u *= aFlag; 35 } 36 37 typedef class SegTreeNode { 38 public: 39 long long sum; 40 int l, r; 41 SegTreeNode *left, *right; 42 int lazy; 43 SegTreeNode():sum(0), l(0), r(0), left(NULL), right(NULL), lazy(0){ } 44 SegTreeNode(int l, int r):sum(0), l(l), r(r), left(NULL), right(NULL), lazy(0){ } 45 46 inline void pushUp(){ 47 this->sum = this->left->sum + this->right->sum; 48 } 49 50 inline void pushDown(){ 51 left->sum = (left->r - left->l + 1) * 1LL * lazy; 52 left->lazy = lazy; 53 right->sum = (right->r - right->l + 1) * 1LL * lazy; 54 right->lazy = lazy; 55 lazy = 0; 56 } 57 }SegTreeNode; 58 59 typedef class SegTree { 60 public: 61 SegTreeNode* root; 62 63 SegTree():root(NULL){ } 64 SegTree(int size, int* list){ 65 build(root, 1, size, list); 66 } 67 68 void build(SegTreeNode*& node, int l, int r, int* list){ 69 node = new SegTreeNode(l, r); 70 if(l == r){ 71 node->sum = list[l]; 72 return; 73 } 74 int mid = (l + r) >> 1; 75 build(node->left, l, mid, list); 76 build(node->right, mid + 1, r, list); 77 node->pushUp(); 78 } 79 80 void update(SegTreeNode*& node, int l, int r, long long val){ 81 if(node->l == l && node->r == r){ 82 node->sum = (r - l + 1) * val; 83 node->lazy = val; 84 return; 85 } 86 if(node->lazy) node->pushDown(); 87 int mid = (node->l + node->r) >> 1; 88 if(r <= mid) update(node->left, l, r, val); 89 else if(l > mid) update(node->right, l, r, val); 90 else{ 91 update(node->left, l, mid, val); 92 update(node->right, mid + 1, r, val); 93 } 94 node->pushUp(); 95 } 96 97 long long query(SegTreeNode*& node, int l, int r){ 98 if(node->l == l && node->r == r){ 99 return node->sum; 100 } 101 if(node->lazy) node->pushDown(); 102 int mid = (node->l + node->r) >> 1; 103 if(r <= mid) return query(node->left, l, r); 104 if(l > mid) return query(node->right, l, r); 105 return query(node->left, l, mid) + query(node->right, mid + 1, r); 106 } 107 }SegTree; 108 109 int n, m; 110 int* list; 111 SegTree st; 112 113 inline void init(){ 114 readInteger(n); 115 list = new int[(const int)(n + 1)]; 116 for(int i = 1; i <= n; i++) 117 readInteger(list[i]); 118 readInteger(m); 119 st = SegTree(n, list); 120 } 121 122 inline void solve(){ 123 char cmd[10]; 124 int a, b, c; 125 while(m--){ 126 scanf("%s", cmd); 127 readInteger(a); 128 readInteger(b); 129 if(cmd[0] == \'m\'){ 130 readInteger(c); 131 st.update(st.root, a, b, c); 132 }else{ 133 long long res = st.query(st.root, a, b); 134 printf(AUTO"\\n", res); 135 } 136 } 137 } 138 139 int main(){ 140 freopen("setsum.in", "r", stdin); 141 freopen("setsum.out", "w", stdout); 142 init(); 143 solve(); 144 return 0; 145 }
dfs序弄一下然后加一个树状数组/线段树就可以轻松应付后面的操作,然而我不小心在建树的时候,用下标为节点编号进行建树而不是访问时间(这个问题很诡异,看着数组完全不知道在干什么),于是愉快地只有10分。
用树状数组要快一点,只不过我比较懒,一二题的线段树模板差距不但,粘过来改一下就行了。
Code
1 #include<iostream> 2 #include<sstream> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<cctype> 8 #include<queue> 9 #include<set> 10 #include<map> 11 #include<stack> 12 #include<vector> 13 #include<algorithm> 14 using namespace std; 15 typedef bool boolean; 16 #ifdef WIN32 17 #define AUTO "%I64d" 18 #else 19 #define AUTO "%lld" 20 #endif 21 #define smin(a, b) (a) = min((a), (b)) 22 #define smax(a, b) (a) = max((a), (b)) 23 template<typename T> 24 inline void readInteger(T& u){ 25 char x; 26 int aFlag = 1; 27 while(!isdigit((x = getchar())) && x != \'-\'); 28 if(x == \'-\'){ 29 aFlag = -1; 30 x = getchar(); 31 } 32 for(u = x - \'0\'; isdigit((x = getchar())); u = u * 10 + x - \'0\'); 33 ungetc(x, stdin); 34 u *= aFlag; 35 } 36 37 typedef class SegTreeNode { 38 public: 39 long long sum; 40 int l, r; 41 SegTreeNode *left, *right; 42 SegTreeNode():sum(0), l(0), r(0), left(NULL), right(NULL){ } 43 SegTreeNode(int l, int r):sum(0), l(l), r(r), left(NULL), right(NULL){ } 44 inline void pushUp(){ 45 this->sum = this->left->sum + this->right->sum; 46 } 47 }SegTreeNode; 48 49 typedef class SegTree { 50 public: 51 SegTreeNode* root; 52 53 SegTree():root(NULL){ } 54 SegTree(int size, int* list, int* keyer){ 55 build(root, 1, size, list, keyer); 56 } 57 58 void build(SegTreeNode*& node, int l, int r, int* list, int* keyer){ 59 node = new SegTreeNode(l, r); 60 if(l == r){ 61 node->sum = list[keyer[l]]; 62 return; 63 } 64 int mid = (l + r) >> 1; 65 build(node->left, l, mid, list, keyer); 66 build(node->right, mid + 1, r, list, keyer); 67 node->pushUp(); 68 } 69 70 void update(SegTreeNode*& node, int index, long long val){ 71 if(node->l == index && node->r == index){ 72 node->sum += val; 73 return; 74 } 75 int mid = (node->l + node->r) >> 1; 76 if(index <= mid) update(node->left, index, val); 77 else update(node->right, index, val); 78 node->pushUp(); 79 } 80 81 long long query(SegTreeNode*& node, int l, int r){ 82 if(node->l == l && node->r == r){ 83 return node->sum; 84 } 85 int mid = (node->l + node->r) >> 1; 86 if(r <= mid) return query(node->left, l, r); 87 if(l > mid) return query(node->right, l, r); 88 return query(node->left, l, mid) + query(node->right, mid + 1, r); 89 } 90 }SegTree; 91 92 typedef class Edge{ 93 public: 94 int end; 95 int next; 96 Edge(const int end = 0, const int next = 0):end(end), next(next){ } 97 }Edge; 98 99 typedef class MapManager{ 100 public: 101 int ce; 102 int *h; 103 Edge* edges; 104 MapManager():ce(0), h(NULL), edges(NULL){ } 105 MapManager(int points, int limits):ce(0){ 106 h = new int[(const int)(points + 1)]; 107 edges = new Edge[(const int)(limits + 1)]; 108 memset(h, 0, sizeof(int) * (points + 1)); 109 } 110 inline void addEdge(int from, int end){ 111 edges[++ce] = Edge(end, h[from]); 112 h[from] = ce; 113 } 114 inline void addDoubleEdge(int from, int end){ 115 addEdge(from, end); 116 addEdge(end, from); 117 } 118 Edge& operator [](int pos){ 119 return edges[pos]; 120 } 121 }MapManager; 122 123 #define m_begin(g, i) (g).h[(i)] 124 125 int n, m; 126 int cnt = 0; 127 int* list; 128 int* keyer; 129 int* visitID; 130 int* exitID; 131 SegTree st; 132 MapManager g; 133 134 void dfs(int node, int last){ 135 visitID[node] = ++cnt; 136 keyer[cnt] = node; 137 for(int i = m_begin(g, node); i != 0; i = g[i].next){ 138 int &e = g[i].end; 139 if(e == last) continue; 140 dfs(e, node); 141 } 142 exitID[node] = cnt; 143 } 144 145 inline void init(){ 146 readInteger(n); 147 list = new int[(const int)(n + 1)]; 148 g = MapManager(n, n * 2); 149 for(int i = 1; i <= n; i++) 150 readInteger(list[i]); 151 for(int i = 1, a, b; i < n; i++){ 152 readInteger(a); 153 readInteger(b); 154 g.addDoubleEdge(a, b); 155 } 156 visitID = new int[(const int)(n + 1)]; 157 exitID = new int[(const int)(n + 1)]; 158 keyer = new int[(const int)(n + 1)]; 159 dfs(1, 0); 160 readInteger(m); 161 st = SegTree(n, list, keyer); 162 } 163 164 inline void solve(){ 165 char cmd[10]; 166 int a, b; 167 while(m--){ 168 scanf("%s", cmd); 169 readInteger(a); 170 if(cmd[0] == \'m\'){ 171 readInteger(b); 172 st.update(st.root, visitID[a], b); 173 }else{ 174 long long res = st.query(st.root, visitID[a], exitID[a]); 175 printf(AUTO"\\n", res); 176 } 177 } 178 } 179 180 int main(){ 181 freopen("subtree.in", "r", stdin); 182 freopen("subtree.out", "w", stdout); 183 init(); 184 solve(); 185 return 0; 186 }
不过我并没有写st表,而是一种很粗暴的方法——树套树(据说线段树套线段树特别牛逼)。
一个线段树负责一行的最大公约数。套外面的线段树就负责合并列的线段树。还有可以加优化,查询的时候,查到的值为1,就return 1。实测效果不错,综合下来,windows随机数据才0.8s。(然而诡异的cena需要1.9s,指针户吃亏啊。。。)
Code(初次树套树比平衡树短)
1 #include<iostream> 2 #include<sstream> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<cctype> 8 #include<queue> 9 #include<set> 10 #include<map> 11 #include<stack> 12 #include<vector> 13 #include<algorithm> 14 #include<ctime> 15 using namespace std; 16 typedef bool boolean; 17 #ifdef WIN32 18 #define AUTO "%I64d" 19 #else 20 #define AUTO "%lld" 21 #endif 22 #define smin(a, b) (a) = min((a), (b)) 23 #define smax(a, b) (a) = max((a), (b)) 24 template<typename T> 25 inline void readInteger(T& u){ 26 char x; 27 int aFlag = 1; 28 while(!isdigit((x = getchar())) && x != \'-\'); 29 if(x == \'-\'){ 30 aFlag = -1; 31 x = getchar(); 32 } 33 for(u = x - \'0\'; isdigit((x = getchar())); u = u * 10 + x - \'0\'); 34 ungetc(x, stdin); 35 u *= aFlag; 36 } 37 38 template<typename T> 39 inline T gcd(T a, T b){ 40 return (b == 0) ? (a) : (gcd(b, a % b)); 41 } 42 43 template<typename T> 44 class Matrix{ 45 public: 46 T* p; 47 int lines, rows; 48 Matrix():p(NULL), lines(0), rows(0){ } 49 Matrix(int rows, int lines):rows(rows), lines(lines){ 50 p = new T[rows * lines]; 51 } 52 T* operator [](int pos){ 53 return p + pos * lines; 54 } 55 }; 56 57 typedef class SegTreeNode1{ 58 public: 59 int val; [kuangbin] 专题13 基础计算几何 题解 + 总结培训补坑(day7:线段树的区间修改与运用)(day6是测试,测试题解以后补坑QAQ)