2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G Xor lca+暴力

来源:互联网 发布:马小丝的淘宝店 编辑:程序博客网 时间:2024/06/05 09:53


题目链接:https://nanti.jisuanke.com/t/17120

题意:给你一棵树,每个点都有权值,q次询问,每次询问给你a,b,k,问从点a到点b每隔k步的异或和是多少。

思路:现场没敢打,复杂度怎么算都不对。。。后来别人说可以1的情况lca其他暴力,我就试了一下,一开始是TLE,然后我各种迷之优化确实可以过。。。。走k步这里我是用了倍增的数组然后用logk的复杂度走k步。。。然后没用memset。。或者加个输入挂我试过也可以过。最后我还有一步没有优化的就是lca没用rmq,直接用的倍增,已经码得够多了不想码rmq了。下面给代码:

#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream>  #include<cmath>  #include<queue>  #include<cstdio>  #include<queue>  #include<algorithm>  #include<cstring>  #include<string>  #include<utility>#include<set>#include<map>#include<stack>#include<vector>#define maxn 50005#define inf  0x3f3f3f3f3f3f3f3fusing namespace std;typedef long long LL;const double eps = 1e-8;const int mod = 1e9 + 7;const int MAXN = 100005;const int M = 20;struct node{int v, value, next;}p[maxn << 1];int len, head[maxn], dis[maxn], depth[maxn], n, m, father[maxn][25], a[maxn], b[maxn];void addedge(int u, int v){p[len].v = v;p[len].next = head[u];head[u] = len++;}void dfs(int x, int fa){father[x][0] = fa;b[x] = b[fa] ^ a[x];for (int i = head[x]; ~i; i = p[i].next){if (p[i].v == fa)continue;depth[p[i].v] = depth[x] + 1;dfs(p[i].v, x);}}void presolve(){dis[1] = depth[1] = 0;dfs(1, 0);for (int i = 1; i < M; i++)for (int j = 1; j <= n; j++)father[j][i] = father[father[j][i - 1]][i - 1];}int lca(int x, int y){if (depth[x] != depth[y]){if (depth[x] > depth[y])swap(x, y);int distant = depth[y] - depth[x];for (int i = 0; i < M; i++){if (distant&(1 << i))y = father[y][i];}}if (x == y)return x;for (int i = M; i >= 0; i--){if (father[x][i] != father[y][i]){x = father[x][i];y = father[y][i];}}return father[x][0];}int find(int x, int k){int now = x, tmp = 0;while (k){if (k & 1)now = father[now][tmp];k >>= 1;tmp++;}return now;}int query(int x, int y, int k){if (k == 1)return b[x] ^ b[y] ^ a[lca(x, y)];else{int nowlca = lca(x, y);int now = x;int ans = 0;while (1){ans ^= a[now];if (depth[now] - k < depth[nowlca])break;now = find(now, k);}int ed = depth[nowlca] + k - depth[now] + depth[nowlca];if (ed <= depth[y]){int tmp = depth[y] - ed;now = find(y, tmp%k);while (1){ans ^= a[now];if (depth[now] - k < ed)break;now = find(now, k);}}return ans;}}int main(){int q;while (~scanf("%d%d", &n, &q)){for (int i = 1; i <= n; i++)head[i] = -1;for (int i = 1; i < n; i++){int u, v;scanf("%d%d", &u, &v);addedge(u, v);addedge(v, u);}for (int i = 1; i <= n; i++)scanf("%d", &a[i]);presolve();while (q--){int u, v, k;scanf("%d%d%d", &u, &v, &k);printf("%d\n", query(u, v, k));}}}


阅读全文
0 0