SPOJ QTREE 系列解题报告
题目一 : SPOJ 375 Query On a Tree
http://www.spoj.com/problems/QTREE/
给一个树,求a,b路径上最大边权,或者修改a,b边权为t。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 7 using namespace std; 8 const int maxn = 200000 + 5; 9 10 int N,pos=0; 11 char ss[50]; 12 13 struct SegmentTree{ 14 int l,r,flag; 15 int maxv,minv; 16 }Node[maxn * 10]; 17 18 int e[maxn][4]; 19 int size[maxn],dep[maxn],top[maxn],son[maxn]; 20 int fa[maxn],Segnum[maxn],Treenum[maxn]; 21 22 int tot = 0; 23 int first[maxn],next[maxn*2]; 24 int u[maxn*2],v[maxn*2]; 25 26 void clear(); 27 void change(int&,int&); 28 void Add(int,int); 29 void dfs_1(int,int,int); 30 void dfs_2(int,int); 31 void build(int,int,int); 32 void update(int,int,int,int); 33 int query(int,int,int); 34 int find_max(int,int); 35 void rever(int,int,int); 36 void get_rever(int,int); 37 void pushdown(int); 38 void pushup(int); 39 40 int main(){ 41 int tcase; 42 scanf("%d",&tcase); 43 while(tcase --){ 44 clear(); 45 int x,y,z; 46 scanf("%d",&N); 47 for(int i = 1;i < N;++ i){ 48 scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); 49 Add(e[i][0],e[i][1]); 50 Add(e[i][1],e[i][0]); 51 } 52 53 dfs_1(1,0,1); 54 dfs_2(1,1); 55 build(1,1,N); 56 for(int i = 1;i < N;++ i){ 57 if(dep[e[i][0]] > dep[e[i][1]]) 58 swap(e[i][0],e[i][1]); 59 update(1,Segnum[e[i][1]],Segnum[e[i][1]],e[i][2]); 60 } 61 while(1){ 62 scanf("%s",ss); 63 if(ss[0] == 'D') 64 break; 65 scanf("%d%d",&x,&y); 66 if(ss[0] == 'C'){ 67 update(1,Segnum[e[x][1]],Segnum[e[x][1]],y); 68 } 69 else if(ss[0] == 'Q'){ 70 printf("%d\n",find_max(x,y)); 71 } 72 else if(ss[0] == 'N'){ 73 get_rever(x,y); 74 } 75 } 76 } 77 return 0; 78 } 79 80 void clear(){ 81 pos = 0;tot = 0; 82 memset(son,0,sizeof son); 83 memset(first,0,sizeof first); 84 } 85 void Add(int s,int t){ 86 ++ tot; 87 u[tot] = s;v[tot] = t; 88 next[tot] = first[u[tot]]; 89 first[u[tot]] = tot; 90 } 91 void dfs_1(int now,int f,int depth){ 92 size[now] = 1; 93 fa[now] = f; 94 dep[now] = depth; 95 96 for(int i = first[now];i;i = next[i]){ 97 if(v[i] != f){ 98 dfs_1(v[i],now,depth + 1); 99 size[now] += size[v[i]]; 100 if(!son[now] || size[v[i]] > size[son[now]]) 101 son[now] = v[i]; 102 } 103 } 104 return; 105 } 106 107 void dfs_2(int now,int ances){ 108 top[now] = ances; 109 Segnum[now] = ++ pos; 110 Treenum[Segnum[now]] = now; 111 112 if(!son[now])return; 113 dfs_2(son[now],ances); 114 115 for(int i = first[now];i;i = next[i]){ 116 if(v[i] != son[now] && v[i] != fa[now]){ 117 dfs_2(v[i],v[i]); 118 } 119 } 120 return; 121 } 122 123 void build(int o,int l,int r){ 124 Node[o].l = l; 125 Node[o].r = r; 126 Node[o].minv = Node[o].maxv = 0; 127 Node[o].flag = 0; 128 if(l == r) 129 return; 130 int Mid = (l + r) >> 1; 131 build(o<<1,l,Mid); 132 build(o<<1|1,Mid+1,r); 133 } 134 135 void update(int o,int l,int r,int v){ 136 if(Node[o].l == l && Node[o].r == r){ 137 Node[o].minv = Node[o].maxv = v; 138 Node[o].flag = 0; 139 return; 140 } 141 int Mid = (Node[o].l + Node[o].r) >> 1; 142 pushdown(o); 143 if(r <= Mid) 144 update(o<<1,l,r,v); 145 else if(l > Mid) 146 update(o<<1|1,l,r,v); 147 pushup(o); 148 } 149 void pushdown(int o){ 150 if(Node[o].l == Node[o].r) 151 return; 152 int lc = o << 1,rc = o << 1 | 1; 153 if(Node[o].flag){ 154 Node[o].flag = 0; 155 Node[lc].flag ^= 1; 156 Node[rc].flag ^= 1; 157 change(Node[rc].minv,Node[rc].maxv); 158 change(Node[lc].maxv,Node[lc].minv); 159 } 160 } 161 void pushup(int o){ 162 int lc = o << 1,rc = o << 1 | 1; 163 Node[o].maxv = max(Node[lc].maxv,Node[rc].maxv); 164 Node[o].minv = min(Node[lc].minv,Node[rc].minv); 165 } 166 167 int query(int o,int l,int r){ 168 if(Node[o].l == l && Node[o].r == r){ 169 return Node[o].maxv; 170 } 171 int Mid = (Node[o].l + Node[o].r) >> 1; 172 pushdown(o); 173 if(r <= Mid) 174 return query(o<<1,l,r); 175 else if(l > Mid) 176 return query(o<<1|1,l,r); 177 else 178 return max(query(o<<1,l,Mid),query(o<<1|1,Mid+1,r)); 179 pushup(o); 180 } 181 void rever(int o,int l,int r){ 182 if(Node[o].l == l && Node[o].r == r){ 183 change(Node[o].maxv,Node[o].minv); 184 Node[o].flag ^= 1; 185 return; 186 } 187 int Mid = (Node[o].l + Node[o].r) >> 1; 188 pushdown(o); 189 if(r <= Mid) 190 rever(o<<1,l,r); 191 else if(l > Mid) 192 rever(o<<1|1,l,r); 193 else{ 194 rever(o<<1,l,Mid); 195 rever(o<<1|1,Mid+1,r); 196 } 197 pushup(o); 198 } 199 int find_max(int x,int y){ 200 int f1 = top[x],f2 = top[y]; 201 int ret = -100000; 202 203 while(f1 != f2){ 204 if(dep[f1] < dep[f2]){ 205 swap(f1,f2); 206 swap(x,y); 207 } 208 ret = max(ret,query(1,Segnum[f1],Segnum[x])); 209 x = fa[f1];f1 = top[x]; 210 } 211 212 if(x == y)return ret; 213 if(dep[x] < dep[y]){ 214 ret = max(ret,query(1,Segnum[son[x]],Segnum[y])); 215 } 216 else{ 217 ret = max(ret,query(1,Segnum[son[y]],Segnum[x])); 218 } 219 220 return ret; 221 } 222 223 void get_rever(int x,int y){ 224 int f1 = top[x],f2 = top[y]; 225 226 while(f1 != f2){ 227 if(dep[f1] < dep[f2]){ 228 swap(f1,f2); 229 swap(x,y); 230 } 231 rever(1,Segnum[f1],Segnum[x]); 232 x = fa[f1];f1 = top[x]; 233 } 234 if(x == y)return;//如果是针对边的操作, 这个东西不能少。。 235 if(dep[x] < dep[y]){ 236 rever(1,Segnum[son[x]],Segnum[y]);//如果是边权,注意这里的写法。要下放。 237 } 238 else{ 239 rever(1,Segnum[son[y]],Segnum[x]); 240 } 241 return; 242 } 243 244 void change(int &a,int &b){ 245 int tp1 = a,tp2 = b; 246 a = -tp2;b = -tp1; 247 return; 248 }
TLE的但是保证 不WA的LCT
1 #include <cstdlib> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std; 8 const int N = 20000 + 5; 9 10 int n; 11 int top, st[N << 1]; 12 int fa[N], c[N][2], val[N], mx[N]; 13 bool rev[N]; 14 15 void pushup(int x) { 16 int l = c[x][0], r = c[x][1]; 17 mx[x] = x; 18 if(l && val[mx[l]] > val[mx[x]]) mx[x] = mx[l]; 19 if(r && val[mx[r]] > val[mx[x]]) mx[x] = mx[r]; 20 } 21 22 void pushdown(int x) { 23 int l = c[x][0], r = c[x][1]; 24 if(rev[x]) { 25 rev[x] ^= 1; rev[l] ^= 1; rev[r] ^= 1; 26 swap(c[x][0], c[x][1]); 27 } 28 } 29 30 bool isroot(int x) { 31 return c[fa[x]][0] != x && c[fa[x]][1] != x; 32 } 33 34 void rotate(int x) { 35 int y = fa[x], z = fa[y], l, r; 36 if(c[y][0] == x) l = 0, r = 1; 37 else l = 1, r = 0; 38 if(!isroot(y)) { 39 if(c[z][0] == y) c[z][0] = x; 40 else c[z][1] = x; 41 } 42 fa[x] = z; fa[y] = x; fa[c[x][r]] = y; 43 c[y][l] = c[x][r]; c[x][r] = y; 44 pushup(y); pushup(x); 45 } 46 47 void splay(int x) { 48 top = 0; st[++ top] = x; 49 for(int i = x; !isroot(i); i = fa[i]) 50 st[++ top] = fa[i]; 51 while(top) pushdown(st[top --]); 52 while(!isroot(x)) { 53 int y = fa[x], z = fa[y]; 54 if(!isroot(y)) { 55 if((c[z][0] == y) ^ (c[y][0] == x)) rotate(x); 56 else rotate(y); 57 } 58 rotate(x); 59 } 60 pushup(x); 61 } 62 63 void access(int x) { 64 int t = 0; 65 while(x) { 66 splay(x); c[x][1] = t; 67 t = x; 68 pushup(x); x = fa[x]; 69 } 70 } 71 72 void mroot(int x) { 73 access(x); splay(x); rev[x] ^= 1; 74 } 75 76 void link(int a, int b) { 77 mroot(a); fa[a] = b; 78 } 79 80 void cut(int a, int b) { 81 mroot(a); access(b); splay(b); 82 c[b][0] = fa[c[b][0]] = 0; 83 } 84 85 int Q(int a, int b) { 86 mroot(a); access(b); splay(b); 87 return val[mx[b]]; 88 } 89 90 void C(int a, int b) { 91 access(a + n); splay(a + n); 92 val[a + n] = b; 93 } 94 95 int main() { 96 char ss[10]; 97 int a, b, t, cs; 98 scanf("%d", &t); 99 while(t --) { 100 memset(fa, 0, sizeof fa); 101 memset(rev, 0, sizeof rev); 102 memset(c, 0, sizeof c); 103 memset(mx, 0, sizeof mx); 104 memset(val, 0, sizeof val); 105 scanf("%d", &n); 106 for(int i = 1; i < n; ++ i) { 107 scanf("%d%d%d", &a, &b, &cs); 108 val[i + n] = cs; 109 mx[i + n] = i + n; 110 link(a, i + n); link(b, i + n); 111 } 112 while(1) { 113 scanf("%s", ss); 114 if(ss[0] == 'D') break; 115 if(ss[0] == 'C') { 116 scanf("%d%d", &a, &b); 117 C(a, b); 118 } 119 else { 120 scanf("%d%d", &a, &b); 121 printf("%d\n", Q(a, b)); 122 } 123 } 124 } 125 return 0; 126 }
题目二: SPOJ Query On a Tree II
题目大意:
给一个树,两个操作,求a->b距离,求a->b路径上的第k个点。
算法讨论:
用LCA来维护,第k个点也用Lca来跳就可以啦。
1 #include <cstdlib> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std; 8 9 const int N = 20000 + 5; 10 11 int n, cnt; 12 int head[N], fa[N], f[N][16]; 13 int dis[N], depth[N]; 14 15 struct Edge { 16 int from, to, dis, next; 17 }edges[N << 1]; 18 19 void insert(int from, int to, int w) { 20 ++ cnt; 21 edges[cnt].from = from; edges[cnt].to = to; edges[cnt].dis = w; 22 edges[cnt].next = head[from]; head[from] = cnt; 23 } 24 25 void build(int u, int f) { 26 fa[u] = f; 27 for(int i = head[u]; i; i = edges[i].next) { 28 int v = edges[i].to; 29 if(v != f) { 30 dis[v] = dis[u] + edges[i].dis; 31 depth[v] = depth[u] + 1; 32 build(v, u); 33 } 34 } 35 } 36 37 void prepare() { 38 memset(f, -1, sizeof f); 39 for(int i = 1; i <= n; ++ i) f[i][0] = fa[i]; 40 for(int j = 1; (1 << j) <= n; ++ j) { 41 for(int i = 1; i <= n; ++ i) { 42 if(f[i][j - 1] != -1) { 43 f[i][j] = f[f[i][j - 1]][j - 1]; 44 } 45 } 46 } 47 } 48 49 int lca(int a, int b) { 50 int i; 51 if(depth[a] < depth[b]) swap(a, b); 52 for(i = 0; (1 << i) <= depth[a]; ++ i); 53 -- i; 54 for(int j = i; j >= 0; -- j) { 55 if(depth[a] - depth[b] >= (1 << j)) 56 a = f[a][j]; 57 } 58 if(a == b) return a; 59 for(int j = i; j >= 0; -- j) { 60 if(f[a][j] != -1 && f[a][j] != f[b][j]) { 61 a = f[a][j]; b = f[b][j]; 62 } 63 } 64 return f[a][0]; 65 } 66 67 int splca(int a, int len) { 68 int i; 69 for(i = 0; (1 << i) <= depth[a]; ++ i); 70 -- i; 71 for(int j = i; j >= 0; -- j) { 72 if(depth[a] - len >= (1 << j)) { 73 a = f[a][j]; 74 } 75 } 76 return a; 77 } 78 79 int Q(int a, int b) { 80 return dis[a] + dis[b] - 2 * dis[lca(a, b)]; 81 } 82 83 int K(int a, int b, int c) { 84 int Lca = lca(a, b), res; 85 if(depth[a] - depth[Lca] + 1 >= c) { 86 res = splca(a, depth[Lca] + (depth[a] - depth[Lca]) - c + 1); 87 } 88 else { 89 c -= (depth[a] - depth[Lca]); 90 res = splca(b, depth[Lca] + c - 1); 91 } 92 return res; 93 } 94 95 void clear() { 96 cnt = 0; 97 memset(head, 0, sizeof head); 98 } 99 100 int main() { 101 int t, u, v, w, a, b, c; 102 char ss[10]; 103 bool flag = false; 104 scanf("%d", &t); 105 while(t --) { 106 if(flag) puts(""); 107 flag = true; 108 clear(); 109 scanf("%d", &n); 110 for(int i = 1; i < n; ++ i) { 111 scanf("%d%d%d", &u, &v, &w); 112 insert(u, v, w); insert(v, u, w); 113 } 114 depth[1] = 1; 115 dis[1] = 0; 116 build(1, 0); 117 prepare(); 118 while(1) { 119 scanf("%s", ss); 120 if(ss[0] == 'D') { 121 if(ss[1] == 'O') break; 122 else { 123 scanf("%d%d", &a, &b); 124 printf("%d\n", Q(a, b)); 125 } 126 } 127 else { 128 scanf("%d%d%d", &a, &b, &c); 129 printf("%d\n", K(a, b, c)); 130 } 131 } 132 } 133 return 0; 134 }
题目三 SPOJ Query On a Tree III
题目大意:
给出一棵树,每个点有权值,而且互不相同。求以某个点为根的子树中第k小的权值是哪个点。
算法讨论:
我的第一个做法是可持久化线段树 + 区间第K小值。我们知道一个点的子树在DFS序中一定是连续的,所以我们可以查询这个区间的第K小值。这就是可持久化线段树的应用。注意可持久化线段树是NlogN的空间,我居然忘记了,只开了原来的4倍。。。所以有三个点re了。
1 #include <cstdlib> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std; 8 9 const int N = 150000 + 5; 10 11 int n, m, cnt, tot, pos; 12 int fa[N], size[N], num[N], mx[N], w[N]; 13 int root[N], rank[N], son[N], head[N], seg[N]; 14 15 struct Edge { 16 int from, to, next; 17 }edges[N << 1]; 18 19 struct SegTree { 20 int l, r, size; 21 }Node[N * 16];//注意可持久化线段树是NlogN的空间 22 23 struct data { 24 int v, pos, id; 25 bool operator < (const data &k) const { 26 return v < k.v; 27 } 28 }a[N]; 29 30 void insert(int from, int to) { 31 ++ cnt; 32 edges[cnt].from = from; edges[cnt].to = to; 33 edges[cnt].next = head[from]; head[from] = cnt; 34 } 35 36 void dfs_1(int x, int f) { 37 size[x] = 1; 38 fa[x] = f; 39 for(int i = head[x]; i; i = edges[i].next) { 40 int v = edges[i].to; 41 if(v != f) { 42 dfs_1(v, x); 43 size[x] += size[v]; 44 if(!son[x] || size[v] > size[son[x]]) 45 son[x] = v; 46 } 47 } 48 } 49 50 void dfs_2(int x, int ances) { 51 mx[x] = num[x] = ++ pos; 52 seg[pos] = x; 53 if(!son[x]) return; 54 dfs_2(son[x], ances); 55 mx[x] = max(mx[x], mx[son[x]]); 56 for(int i = head[x]; i; i = edges[i].next) { 57 int v = edges[i].to; 58 if(v != fa[x] && v != son[x]) { 59 dfs_2(v, v); 60 mx[x] = max(mx[x], mx[v]); 61 } 62 } 63 } 64 65 void build(int &o, int l, int r) { 66 o = ++ tot; 67 Node[o].l = Node[o].r = Node[o].size = 0; 68 if(l >= r) return; 69 int mid = (l + r) >> 1; 70 build(Node[o].l, l, mid); 71 build(Node[o].r, mid + 1, r); 72 } 73 74 void update(int pre, int &o, int l, int r, int kth) { 75 o = ++ tot; 76 Node[o] = Node[pre]; 77 Node[o].size ++; 78 if(l >= r) return; 79 int mid = (l + r) >> 1; 80 if(kth <= mid) 81 update(Node[pre].l, Node[o].l, l, mid, kth); 82 else 83 update(Node[pre].r, Node[o].r, mid + 1, r, kth); 84 } 85 86 int query(int r1, int r2, int l, int r, int kth) { 87 if(l >= r) return l; 88 int lc = Node[Node[r2].l].size - Node[Node[r1].l].size; 89 int mid = (l + r) >> 1; 90 if(lc >= kth) { 91 int ans = query(Node[r1].l, Node[r2].l, l, mid, kth); 92 return ans; 93 } 94 else { 95 int ans = query(Node[r1].r, Node[r2].r, mid + 1, r, kth - lc); 96 return ans; 97 } 98 } 99 100 int Q(int x, int k) { 101 int l = num[x], r = mx[x]; 102 return a[query(root[l - 1], root[r], 1, n, k)].id; 103 } 104 105 int main() { 106 int u, v, x, k; 107 scanf("%d", &n); 108 for(int i = 1; i <= n; ++ i) scanf("%d", &w[i]); 109 for(int i = 1; i < n; ++ i) { 110 scanf("%d%d", &u, &v); 111 insert(u, v); insert(v, u); 112 } 113 dfs_1(1, 0); dfs_2(1, 1); 114 for(int i = 1; i <= n; ++ i) { 115 a[i].v = w[seg[i]]; 116 a[i].pos = i; 117 a[i].id = seg[i]; 118 } 119 sort(a + 1, a + n + 1); 120 for(int i = 1; i <= n; ++ i) { 121 rank[a[i].pos] = i; 122 } 123 build(root[0], 1, n); 124 for(int i = 1; i <= n; ++ i) { 125 update(root[i - 1], root[i], 1, n, rank[i]); 126 } 127 scanf("%d", &m); 128 for(int i = 1; i <= m; ++ i) { 129 scanf("%d%d", &x, &k); 130 printf("%d\n", Q(x, k)); 131 } 132 return 0; 133 }
1 #include <cstdlib> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std; 8 9 const int N = 100000 + 5; 10 11 int n, m, cnt, tot, pos; 12 int fa[N], num[N], mx[N], w[N], st[N << 1]; 13 int root[N], rank[N], head[N], seg[N], fast[N]; 14 15 struct Edge { 16 int from, to, next; 17 }edges[N << 1]; 18 19 struct SegTree { 20 int l, r, size; 21 }Node[N * 20]; 22 23 struct data { 24 int v, pos, id; 25 bool operator < (const data &k) const { 26 return v < k.v; 27 } 28 }a[N]; 29 30 //seg[i] the ith pos is seg[i] 31 //num[i] the i's pos in the segment tree. 32 void dfs() { 33 int top = 0; 34 st[++ top] = 1; 35 while(top) { 36 int now = st[top], f = fast[top]; 37 top --; 38 if(!num[now]) { 39 num[now] = ++ pos; 40 mx[now] = num[now]; 41 st[++ top] = now; 42 fa[now] = f; 43 for(int i = head[now]; i; i = edges[i].next) { 44 if(edges[i].to != f) { 45 st[++ top] = edges[i].to; 46 fast[top] = now; 47 } 48 } 49 } 50 } 51 for(int i = 1; i <= n; ++ i) 52 seg[num[i]] = i; 53 for(int i = n; i >= 1; -- i) { 54 mx[fa[seg[i]]] = max(mx[seg[i]], mx[fa[seg[i]]]); 55 } 56 } 57 58 void insert(int from, int to) { 59 ++ cnt; 60 edges[cnt].from = from; edges[cnt].to = to; 61 edges[cnt].next = head[from]; head[from] = cnt; 62 } 63 64 void build(int &o, int l, int r) { 65 o = ++ tot; 66 Node[o].l = Node[o].r = Node[o].size = 0; 67 if(l >= r) return; 68 int mid = (l + r) >> 1; 69 build(Node[o].l, l, mid); 70 build(Node[o].r, mid + 1, r); 71 } 72 73 void update(int pre, int &o, int l, int r, int kth) { 74 o = ++ tot; 75 Node[o] = Node[pre]; 76 Node[o].size ++; 77 if(l >= r) return; 78 int mid = (l + r) >> 1; 79 if(kth <= mid) 80 update(Node[pre].l, Node[o].l, l, mid, kth); 81 else 82 update(Node[pre].r, Node[o].r, mid + 1, r, kth); 83 } 84 85 int query(int r1, int r2, int l, int r, int kth) { 86 if(l >= r) return l; 87 int lc = Node[Node[r2].l].size - Node[Node[r1].l].size; 88 int mid = (l + r) >> 1; 89 if(lc >= kth) { 90 int ans = query(Node[r1].l, Node[r2].l, l, mid, kth); 91 return ans; 92 } 93 else { 94 int ans = query(Node[r1].r, Node[r2].r, mid + 1, r, kth - lc); 95 return ans; 96 } 97 } 98 99 int Q(int x, int k) { 100 int l = num[x], r = mx[x]; 101 return a[query(root[l - 1], root[r], 1, n, k)].id; 102 } 103 104 int main() { 105 int u, v, x, k; 106 scanf("%d", &n); 107 for(int i = 1; i <= n; ++ i) scanf("%d", &w[i]); 108 for(int i = 1; i < n; ++ i) { 109 scanf("%d%d", &u, &v); 110 insert(u, v); insert(v, u); 111 } 112 dfs(); 113 for(int i = 1; i <= n; ++ i) { 114 a[i].v = w[seg[i]]; 115 a[i].pos = i; 116 a[i].id = seg[i]; 117 } 118 sort(a + 1, a + n + 1); 119 for(int i = 1; i <= n; ++ i) { 120 rank[a[i].pos] = i; 121 } 122 build(root[0], 1, n); 123 for(int i = 1; i <= n; ++ i) { 124 update(root[i - 1], root[i], 1, n, rank[i]); 125 } 126 scanf("%d", &m); 127 for(int i = 1; i <= m; ++ i) { 128 scanf("%d%d", &x, &k); 129 printf("%d\n", Q(x, k)); 130 } 131 return 0; 132 }