2019下学期第二次个人周赛—A题

题意:

如题所示,求\(S(u_1,v_1)\)\(\oplus\)\(S(u_2,v_2)\)的最大值。

分析:

\(1\).暴力解法:既然\(S(u,v)\)与每个点的祖先有关,那么不难想到一个\(O(n^2)\)的方法计算所有\(S(u,v)\)的值,对每个顶点遍历其祖先暴力计算即可。要算\(S(u_1,v_1)\)\(\oplus\)\(S(u_2,v_2)\)的最大值,可以暴力\(O(p^{2})\)的计算,其中\(p\)表示去重后所有\(S(u,v)\)的数目。那么总复杂度就是\(O(p^2)\)的,无法通过本题。\(p\)的最大值不超过\(20000*15\)。

\(2\).我的解法:可以发现每个顶点的权值很小,只需要用一个数组\(vis[N][16]\)来标记\(u\)的祖先到\(u\)这个节点的异或值,当\(dfs\)遍历\(u\)的儿子\(v\)时,再计算标记\(v\)的异或值即可。这样即可\(O(n*16)\)的得到所有\(S(u,v)\)的值。再用一棵\(01\)字典树边插入边查询最大值即可,总复杂度\(O(p*log_2(p))\)。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

#define pb push_back

const int N = 2e4 + 5, M = N * 16 + 5;

int n, u, v, ans, w[N];
bool val[N][17], flag[M];
int tot, ch[M * 19][2];
int head[N], cnt;

struct Graph {
    int v, next;
} edge[N << 1];

void addedge(int u, int v) {
    edge[++cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

void insert(int p) {
    int u = 0, x;
    for (int i = 19; ~i; i--) {
        x = (p >> i) & 1;
        if (!ch[u][x]) ch[u][x] = ++tot;
        u = ch[u][x];
    }
}

int query(int p) {
    int u = 0, x, ans = 0;
    for (int i = 19; ~i; i--) {
        x = (p >> i) & 1;
        if (ch[u][!x]) u = ch[u][!x], ans |= (1 << i);
        else u = ch[u][x];
    }
    return ans;
}

void dfs(int u, int f) {
    val[u][w[u]] = true;
    if (!flag[w[u] * u]) {
        flag[w[u] * u] = true;
        insert(w[u] * u);
        ans = max(ans, query(w[u] * u));
    }
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].v;
        if (v == f) continue;
        for (int j = 0; j <= 15; j++) {
            if (val[u][j]) {
                val[v][j ^ w[v]] = true;
                if (!flag[(j ^ w[v]) * v]) {
                    flag[(j ^ w[v]) * v] = true;
                    insert((j ^ w[v]) * v);
                    ans = max(ans, query((j ^ w[v]) * v));
                }
            }
        }
        dfs(v, u);
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n - 1; i++) {
        scanf("%d %d", &u, &v);
        addedge(u, v), addedge(v, u);
    }
    for (int i = 1; i <= n; i++) scanf("%d", w + i);
    dfs(1, 0);
    printf("%d\n", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/ChaseNo1/p/11745224.html

时间: 2024-10-12 23:37:37

2019下学期第二次个人周赛—A题的相关文章

此文记录了我从研二下学期到研三上学期的找工历程,包括百度、腾讯、网易、移动、电信、华为、中兴、IBM八家企业的面试总结和心得--转

感谢电子通讯工程的研究生学长为大家整理了这么全面的求职总结,希望进入通信公司和互联网公司做非技术类岗位的学弟学妹们千万不要错过哦~ ---------------------------原文分割线-------------------------- 此文记录了我从研二下学期到研三上学期的找工历程,包括百度.腾讯.网易.移动.电信.华为.中兴.IBM八家企业的面试总结和心得,希望能够帮助到正在找工的朋友和师弟师妹们,并纪念找工这段怀揣着希望和梦想,伴随着紧张和压力,同时令我受益匪浅的日子. (本文

大二下学期——期末总结

时至今晚,就意味着大二整年就满满当当.尽心尽力地过去了.前两天开始思考一个问题:这学期的我干了什么?收获了什么?放弃了什么? 凭借着一点点向前回忆,想到了一个悲催的事实,好像这学期都没有给自己放过一整天假,成天感觉自己早出晚归,和老朋友的联系也少了许多.按着月份去总结,2018年3月份开学以来,成绩竟排在系第一.看到成绩那一刻满心愧疚,毕竟上学期自己是靠着抱润哥.爽哥两个大腿在软工概论取得好分数,数据结构.离散数学更是爽哥一手补的等等.再一看,自己分心了团委的工作,似乎给朋朋哥请了一个不知哪是尽

“全栈2019”Java异常第二十章:自定义异常详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异常第二十章:自定义异常详解 下一章 "全栈2019"Java异常第二十一章:finally不被执行的情况 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Java学

“全栈2019”Java多线程第二十五章:生产者与消费者线程详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第二十五章:生产者与消费者线程详解 下一章 "全栈2019"Java多线程第二十六章:同步方法生产者与消费者线程 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"

“全栈2019”Java多线程第二十六章:同步方法生产者与消费者线程

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第二十六章:同步方法生产者与消费者线程 下一章 "全栈2019"Java多线程第二十七章:Lock获取lock/释放unlock锁 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorha

“全栈2019”Java多线程第二十七章:Lock获取lock/释放unlock锁

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第二十七章:Lock获取lock/释放unlock锁 下一章 "全栈2019"Java多线程第二十八章:公平锁与非公平锁详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回

“全栈2019”Java多线程第二十八章:公平锁与非公平锁详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第二十八章:公平锁与非公平锁详解 下一章 "全栈2019"Java多线程第二十九章:可重入锁与不可重入锁详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"J

大三下学期计划

大三下学期计划: 学习C#也有1年多了,对于这门技术也有了大致的了解,相比较java而言,自己还是喜欢C#语言的,更别说宇宙最强大的IDE了. 马上也要找工作了,下面是对于自己这一学期的计划. 1:参加学校的挑战杯,把自己的项目完善,将来找工作的时候可以很好的向HR介绍自己的项目. 2:每天学习点asp.net的基础,mvc在项目中的使用等,自己也要看从图书馆借来的书<C#基础教程><C#5.0入门经典>,看书的时候可以把笔记也在纸上面,这样自己可以很好的复习了. 3:对于数据库的

解题报告——2018级2016第二学期第二周作业

解题报告——2018级2016第二学期第二周作业 D:迷宫问题 题目描述: 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线. 输入 一个5 × 5的二维数组,表示一个迷宫.数据保证有唯一解. 输出 左上角到右