首页 > 其他分享 >Solution - Atcoder AGC052B Tree Edges XOR

Solution - Atcoder AGC052B Tree Edges XOR

时间:2024-07-31 11:59:16浏览次数:12  
标签:Atcoder XOR int 边权 Tree 点权 oplus val0 val1

令 \(w_{(u, v)}\) 为边 \((u, v)\) 的边权。

考虑到对于一条边进行操作影响的是有公共点的边,于是一个想法是把边权转到点权,用点权来表示边权。

于是考虑对于每个点构造 \(w_u\) 使得 \(w_{(u, v)} = w_u\oplus w_v\)。
因为这是一颗树,所以一定存在合法的构造。
其实到了这里,这种构造的方案还只是一种猜想,并不确定是否正确(能正确的表述操作)。

接下来考虑操作一条边 \((u, v)\)。
就相当于是 \(w_u\leftarrow w_u\oplus w_{(u, v)} = w_u\oplus (w_u\oplus w_v) = w_v\),同样的,有 \(w_v\leftarrow w_u\)。
然后能发现此时对于边 \((u, v)\),边权依旧是 \((w_u, w_v)\),对于边 \((u, x)\),边权从 \(w_u\oplus w_x\) 变为了 \(w_v\oplus w_x\),刚好异或的是 \(w_u\oplus w_v = w_{(u, v)}\)。
所以能够知道这种构造方案是正确的。

同时能够发现,这时操作变为了交换相邻两点的点权。
于是可以知道,只要对于每一种点权出现次数的次数都相同,两种局面就一定是可以互相操作出的。

那么只需要把初始边权与终止边权带入,各自跑出一个合法的点权 \(w_{u, 0 / 1}\),向上面这样判定就行了。……吗?

考虑到 \(w_{(u, v)} = w_u\oplus w_v = (w_u\oplus x)\oplus (w_v\oplus x)\),这意味着有可能初始局面会在所有点权都异或上一个值 \(x\) 后才会变成终止局面。

但考虑到若存在合法的 \(x\),一定有 \((w_{1, 0}\oplus x)\oplus \cdots \oplus (w_{n, 0}\oplus x) = w_{1, 1}\oplus \cdots \oplus w_{n, 1}\)。
又因为 \(n\) 为奇数,一定能得到一个 \(x\)。

但是需要注意上面这个条件不是充要条件。
即上面的得到的 \(x\) 依然可能是不合法的,不能保证一一对应。(\(w_{1 \sim 3, 0 / 1} = \begin{bmatrix}0 & 0\\ 0 & 1\\ 0 & 1 \end{bmatrix}\),此时可以得到 \(x = 0\),但代入能发现不合法)。

那么再代入检查一遍是不是一一对应就行了。

时间复杂度 \(\mathcal{O}(n\log n)\),如果最后的检查用基排可以 \(\mathcal{O}(n)\)。

#include<bits/stdc++.h>
const int maxn = 1e5 + 10;
int a[maxn][2];
std::vector<std::tuple<int, int, int> > to[maxn];
void dfs(int u, int fa) {
   for (auto [v, val0, val1] : to[u]) {
      if (v == fa) continue;
      a[v][0] = a[u][0] ^ val0;
      a[v][1] = a[u][1] ^ val1;
      dfs(v, u);
   }
}
int main() {
   int n; scanf("%d", &n);
   for (int i = 1, u, v, val0, val1; i < n; i++) {
      scanf("%d%d%d%d", &u, &v, &val0, &val1);
      to[u].emplace_back(v, val0, val1);
      to[v].emplace_back(u, val0, val1);
   }
   dfs(1, 0);
   int val = 0;
   for (int i = 1; i <= n; i++)
      val ^= a[i][0] ^ a[i][1];
   for (int i = 1; i <= n; i++)
      a[i][0] ^= val;
   std::map<int, int> mp;
   for (int i = 1; i <= n; i++)
      mp[a[i][0]]++, mp[a[i][1]]--;
   for (auto [x, y] : mp)
      if (y)
         return puts("NO"), 0;
   return puts("YES"), 0;
}

标签:Atcoder,XOR,int,边权,Tree,点权,oplus,val0,val1
From: https://www.cnblogs.com/rizynvu/p/18334334

相关文章

  • Atcoder ABC296 F
    AtcoderABC296FF-SimultaneousSwap链接:F-SimultaneousSwap(atcoder.jp)简要题意:问题陈述给你两个\(N\)数字序列:\(A=(A_1,A_2,\ldots,A_N)\)和\(B=(B_1,B_2,\ldots,B_N)\)。高桥可以重复下面的操作任意多次(可能为零)。在\(1\)和\(N\)之间选择三......
  • Atcoder 356 C - Keys 二进制枚举
    原题链接:https://atcoder.jp/contests/abc356/tasks/abc356_c C-Keys:问题陈述您有 N 个编号为1,2,…,N 的密钥。其中一些是真钥匙,其他都是假钥匙。有一扇门,门X,你可以插入任意数量的钥匙。只有插入至少 K 把真钥匙,X门才会打开。你已经对这些钥匙进行了 M 次......
  • Solution - Atcoder APC001E Antennas on Tree
    首先考虑判定什么样的选取是合法的。考虑到令任意一个点\(u\)为根。若\(u\)有至少两个子树没有点选中,那么这两个子树是无法区分的。所以可以知道需要满足任意一个点为根,都至多存在一个子树内部没有选中的点。接下来就要贪心的选出最少的点了。考虑对于每个点的限制都是子......
  • Solution - Atcoder AGC028B Removing Blocks
    因为贡献的方法是相加,一种想法就是拆开,对每一项单独贡献。不难发现这题目中的贡献其实只涉及到两点之间。即删除\(x\)时\(y\)也产生了贡献。考虑这个贡献会在多少种排列中出现。令\(d=|x-y|+1\),即\(x,y\)中的点数。能发现排列需要满足除\(x\)外的\(d-1\)......
  • Atcoder ABC364 D-F
    AtcoderABC364D-FD-K-thNearest链接:D-K-thNearest(atcoder.jp)简要题意:问题陈述在一条数线上有\(N+Q\)个点\(A_1,\dots,A_N,B_1,\dots,B_Q\),其中点\(A_i\)的坐标为\(a_i\),点\(B_j\)的坐标为\(b_j\)。请就每个点\(j=1,2,\dots,Q\)回答下面的问题:......
  • P9058 [Ynoi2004] rpmtdq 与 P9678 [ICPC2022 Jinan R] Tree Distance
    思路:注意到点对数量有\(N^2\)个,考虑丢掉一些无用的点对。对于点对\((x_1,y_1),(x_2,y_2)\),满足\(x_1\lex_2<y_2\ley_1\),即区间\([x_2,y_2]\)被\([x_1,y_1]\)包含,此时满足若询问到了\([x_1,y_1]\),则一定会询问到\([x_2,y_2]\)。若满足\(\operatorname{dis}(x_1......
  • Solution - Atcoder YPC2019E Odd Subrectangles
    首先对于\(0/1\)和为奇数,转化为异或为\(1\)来考虑。考虑如果已经确定了行的选取,又该如何计数。考虑对于每一列,都处理好在对应行的位置的异或值。然后记\(\operatorname{c}_0,\operatorname{c}_1\)表示列异或值为\(0/1\)的数量。知道了\(\operatorname{c}_0,\op......
  • Solution - Atcoder UTPC2023P Priority Queue 3
    考虑找一些关于合法的\(X\)加入的数的判定条件。假设遇到了一个\(\operatorname{pop}\)操作,令这里删除的数为\(a_i\),显然\(X\)中的数应该要有\(a_i\),其次\(X\)中其他的加入的数要么\(>a_i\)要么是\(a\)中的元素(在前面的\(\operatorname{pop}\)就已经被删了)。于......
  • AtCoder Beginner Contest 362
    AtCoderBeginnerContest362前言vp的时候出了四题,被C题卡了一会,很久才出,D题是dijkstra的板子,改下条件即可,E题是个计数dp,这类题一直不怎么擅长,想起之前杭电第一场那个序列立方的题也是类似这种计数dp,需要加强练习。A-BuyaPen(atcoder.jp)思路判断两两最小。......
  • Solution - Atcoder ABC280Ex Substring Sort
    对于这种子串问题,且有多个基础串,一个比较直观的想法就是先上个广义SAM。考虑SAM与字典序如何联系上。因为跳\(\operatorname{fail}\)相当于是删除子串的一个前缀,直接这样子明显是不行的,因为跳了\(\operatorname{fail}\)字典序没有一个很直观地表示。但是反过来考虑反串,......