首页 > 其他分享 >[题解] CF1790E - XOR Tree

[题解] CF1790E - XOR Tree

时间:2023-10-17 21:45:07浏览次数:37  
标签:pre CF1790E XOR int 题解 dfs st auto adj

CF1790E - XOR Tree

题意

给定一颗无根树,在可以改变任意一个点的点权操作基础上,让树上任意简单路径的异或和不为 \(0\) ,问最少需要多少次操作。

思路

假设某个点为根,设 \(pre_x\) 为 \(x\) 点到根的树上前缀异或和, \(a_x\) 为 \(x\) 的点权,则 \(x\) 和 \(y\) 之间简单路径的异或和即为 \(pre_x \oplus pre_y \oplus a_{lca_{x,y}}\) 。那么,自然题目可以转化为 \(pre_x \oplus pre_y \oplus a_{lca_{x,y}} \neq 0\) 。

假设出现违反题目的操作,那么我们可以将 \(a_{lca_{x,y}}\) 改成一个任意大的值,使得该点的子树前缀和无效(或者说加上了一个非常大的值,不会违反题目的情况)。

因此,可以发现,我们并不需要真的去修改点权,对其的修改相当于将以其为根的子树丢弃。那么,我们就可以设当前遍历到的节点为 \(x\) ,是否存在为其子树的节点 \(u\) 和 \(v\) ,使得 \(pre_u \uplus a_x = pre_v\) 。对于这个过程,我们可以将前缀异或和存在 set 之中, dfs 儿子节点后,对两个集合,查看是否出现上述情况,如果出现该情况,那么说明这个点要被修改,信息待会要被掉了。枚举完条件后,需要合并一下信息,相当于凑齐子树信息。这样再一次 dfs 一遍即可。

要注意的一个点是,由于涉及到两个集合合并,因此可以使用启发式合并的方式合并集合。

代码

auto Main() -> void {
    int n;
    cin >> n;

    vector<int> a(n), pre(n);
    for (int i = 0; i < n; i += 1) {
        cin >> a[i];
        pre[i] = a[i];
    }

    vector adj(n, vector<int>{});
    for (int i = 0; i < n - 1; i += 1) {
        int u, v;
        cin >> u >> v;
        u -= 1;
        v -= 1;
        adj[u].emplace_back(v);
        adj[v].emplace_back(u);
    }

    auto dfs1 = [&](auto &self, int from, int come) -> void {
        for (auto to : adj[from]) {
            if (to != come) {
                pre[to] ^= pre[from];
                dfs(dfs, to, from);
            }
        }
    };
    dfs1(dfs1, 0, -1);

    vector<set<int>> st(n);
    int ans = 0;

    auto dfs2 = [&](auto &dfs, int from, int come) -> void {
        st[from].emplace(pre[from]);
        bool need = false;
        for (auto to : adj[from]) {
            if (to == come) {
                continue;
            }
            dfs(dfs, to, from);
            if (need) continue;
            if (st[from].size() < st[to].size()) {
                swap(st[from], st[to]);
            }
            for (auto x : st[to]) {
                if (st[from].contains(x ^ a[from])) {
                    need = true;
                    break;
                }
            }
            st[from].merge(st[to]);
        }
        ans += need;
        if (need) {
            st[from].clear();
        }
    };
    dfs2(dfs2, 0, -1);

    cout << ans << '\n';  
}

标签:pre,CF1790E,XOR,int,题解,dfs,st,auto,adj
From: https://www.cnblogs.com/FlandreScarlet/p/17770783.html

相关文章

  • [题解]CF514D R2D2 and Droid Army
    思路首先,可以转化题意,找到一个极长的区间\([l,r]\)使得(其中\(mx_i\)表示\([l,r]\)区间中属性\(i\)的最大值):\[\sum_{i=1}^{m}mx_i\leqk\]显然对于这个东西当\(l,r\)发生移动时,是极其好维护的,所以想到双指针。因为\(m\leq5\),所以我们可以直接开\(m\)个ST表......
  • 题解——2023年码谷提高组模拟赛1016
    题解——2023年码谷提高组模拟赛1016一套被各种转来转去的题;参考:https://blog.csdn.net/liuziha/article/details/127353981、https://www.luogu.com.cn/blog/Chen5201314/xiao-nei-bi-sai-1025-zong-jie-ti-xie和https://www.cnblogs.com/Clyfort/articles/0927-test-solutio......
  • 「BZOJ2505」tickets 题解
    preface网上目前还没看到我的方法,就大概讲一下做法solution首先想到贪心,考虑\([l,r]\)的最大次数,一定是找到最小的\(x\)满足\(l\simx\)的位数的和大于等于\(k\),然后递归的求解\([x+1,r]\),易证。还是考虑将\(Query(l,r)\)拆分成\(Query(1,r)\)和\(Query......
  • RTMP dimensions not set问题解决方案
    问题RTMP开始推流,打印错误提示:dimensionsnotset源码位置libavformat\mux.ccaseAVMEDIA_TYPE_VIDEO:if((par->width<=0||par->height<=0)&&!(of->flags&AVFMT_NODIMENSIONS)){av_log(s,A......
  • CF1879F Last Man Standing 题解
    原题翻译观察题目,容易发现当题目难度为\(x\)时一个OIer存活时间为\(h_i\lceil\frac{a_i}{x}\rceil\)发现\(a_i\)较小,所以我们先考虑暴力枚举\(x\in[1,\maxa_i]\),然后把原数组按\(a_i\)排个序,对于每组\(\lceil\frac{a_i}{x}\rceil\)相同的部分统一计算他......
  • visual studio智能提示出现慢的问题解决办法
    VisualStudio智能提示出现慢的问题解决办法如下:清理VisualStudio缓存。通过"文件"→"打开文件或项目"→"取消"→"是,清理所有项目"进行清理。清理VisualStudio实例。通过"文件"→"关闭解决方案"进行清理。重置用户数据。打开VisualStudio的开发人员命令提示符,输入devenv.ex......
  • CF1680F Lenient Vertex Cover 题解
    CF1680FLenientVertexCover题解这道题和「JOISC2014Day3」电压非常类似,或者说就是一道题。题意就是给你一个图,问能否对所有点黑白染色,允许最多一条边的两个顶点都染成黑色。黑白染色后其实就是一个二分图,那如果有一条边的两个顶点染成黑色,就是说去掉该边后,剩下的图为二分......
  • 题解:CF237D
    题目传送门思路构造\(k\)个集合,使这些集合满足以下性质:集合的并集为\(V\)。对于树\(s\)中的任意一条边\((a,b)\),都能在\(k\)个集合中找到一个集合\(x\)使得\(a,b\inx\)。对于树\(s\)中的任意一个点\(a\),所有在\(k\)个集合中包含了\(a\)的集合构成了......
  • 题解 P7468【[NOI Online 2021 提高组] 愤怒的小 N】
    题解P7468【[NOIOnline2021提高组]愤怒的小N】problem首先是有一个字符串\(S=\texttt{"0"}\),做无限次“将\(S\)的每一位取反接在\(S\)后面”的操作,形如\(S=0110100110010110\cdots\)。另外给一个\(k-1\)次多项式\(f\),求\(\sum_{i=0}^{n-1}S_if(i).\)\(n\leq......
  • 题解 ABC267F【Exactly K Steps】
    (accoders::NOI#5541.醉(intoxicated))题目描述Robin有一棵树,他有\(m\)次询问,每次询问他给你\(u,k\),你需要输出树上的一个节点\(v\)满足\(dist(u,v)=k\),或者报告无解。\(dist(u,v)\)表示树上\(u\)到\(v\)的最短路径的边数。\(n\leq10^5\)solution考虑求出每个......