题解 | #武侍乐队#

武侍乐队

https://ac.nowcoder.com/acm/contest/11242/C

先dfs预处理出异或和,再用可持久化Trie,pre版本是u,v的的最近公共祖先,now版本是u(v),cnt数组存某个下标的01数量,查询时只cnt[pre]<cnt[now]即可往这个分支走,最后再贪心

#include<bits/stdc++.h>

#define pb push_back
using namespace std;
const int N = 2e5 + 10;
vector<int> v[N];
int x[N], f[N][20], dep[N], xo[N], cnt[32 * N], rt[N], idx, tr[32 * N][2];

void insert(int pre, int now, int val) {
    for (int i = 30; i >= 0; i--) {
        bool v = val >> i & 1;
        tr[now][v ^ 1] = tr[pre][v ^ 1];
        tr[now][v] = ++idx;
        now = tr[now][v];
        pre = tr[pre][v];
        cnt[now] = cnt[pre] + 1;
    }
}

void dfs(int u, int fa) {
    f[u][0] = fa;
    dep[u] = dep[fa] + 1;
    xo[u] = xo[fa] ^ x[u];
    for (int i = 1; i < 20; i++)f[u][i] = f[f[u][i - 1]][i - 1];
    insert(rt[fa], rt[u]=++idx, x[u]);
    for (auto i:v[u])
        if (i != fa)
            dfs(i, u);
}

int lca(int x, int y) {
    if (dep[x] < dep[y])swap(x, y);
    for (int i = 19; i >= 0; i--)
        if (dep[f[x][i]] >= dep[y])
            x = f[x][i];

    if (x == y)return x;

    for (int i = 19; i >= 0; i--)
        if (f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    return f[x][0];
}

int query(int now, int pre, int val) {
    int res = 0;
    for (int i = 30; i >= 0; i--) {
        bool v = val >> i & 1;
        if (cnt[tr[now][v ^ 1]] > cnt[tr[pre][v ^ 1]]) {
            res += 1 << i;
            v^=1;
        }
        now = tr[now][v];
        pre = tr[pre][v];
    }
    return res;
}

int main() {
    int n, m, w;
    scanf("%d%d%d", &n, &m, &w);
    for (int i = 1; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        v[x].pb(y);
        v[y].pb(x);
    }
    for (int i = 1; i <= n; i++)scanf("%d", &x[i]);
    dfs(1, 0);
    while (m--) {
        int a, b, s;
        scanf("%d%d%d", &a, &b, &s);
        int p = lca(a, b);
        int ans = xo[a] ^xo[b] ^x[p];
        int ma = max({query(rt[b], rt[p], s), query(rt[a], rt[p], s), x[p] ^ s});
        ans = ans ^ ma ^ s;
        int res = 0;
        for (int k = 30; ~k; --k)if (!(ans & (1 << k)) && res + (1 << k) <= w)res += (1 << k);
        cout << (ans ^ res) << endl;
    }
    return 0;
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
06-19 14:46
和女友两个人马上毕业,现在我在鹅实习995,周六日偶尔也去北京;她在北京金融007,经常忙到后半夜,周末也没啥休息机会两个人现在都不咋聊天了,一句话隔半小时甚至半天才回。&nbsp;她是个很优秀的妹子,工作也很努力,是值得学习一辈子的人。我在努力工作求转正,即便不行至少赚到了一段不错的实习经历。已经异地了半年,接下来可能还会持续是这个状态。我们都算是对方重要的人,只是感觉看上去不是很有未来的样子。希望牛友们给点的鼓励
梦旅奇缘:很难。异地首先就已经很难了,加上妹子是金融行业,忙碌高压,对情感需求很高,而且见惯纸醉金迷,你的很多优势在她那里可能就不算什么了。这种情况下,在她们那里遇到一个能及时照顾她的人,即使那人可能很多条件不如你,你也有可能被分手。 说白了,两个卷王就不太适合在一起。因为卷王最大的优势,在另一个卷王那里就不算优势了。
点赞 评论 收藏
分享
震撼沃玛一整年:查看图片
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务