为什么 CodeForces 还没上 2100

1929. Codeforces Round 926 (Div. 2)

寄寄寄。

image

image

A. Sasha and the Beautiful Array

容易发现 \(\displaystyle \sum_{i = 2}^{n}(a_i - a_{i - 1}) = a_n - a_1\),令 \(\displaystyle a'_n = \max_{i = 1}^{n}a_i, a'_1 = \min_{i = 1}^{n}a_i\) 即可,其中 \(a'\) 为重排后的数组。

代码:

Code
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/rope>
bool Mbe;
typedef long long i64;
typedef unsigned long long u64;
typedef __int128 i128;
std :: mt19937 rnd (std :: time (0));
template < class T > T gen (const T l, const T r) {return rnd () % (r - l + 1) + l;}
const double pi = std :: acos (-1);
template < class T > inline void read (T &val) {
  T x = 0;
  bool f = false;
  char c = std :: getchar ();
  for ( ; c < '0' || c > '9' ; c = std :: getchar ()) f |= (c == '-');
  for ( ; c >= '0' && c <= '9' ; c = std :: getchar ()) x = (x << 1) + (x << 3) + (c & 15);
  val = (!f) ? (x) : (-x);
  return ;
}
#define debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
const i64 hashmod1 = 2147483579, hashmod2 = 1610612741, hashmod3 = 805306457;
template < class T, class I > void chkmin (T &p, I q) {T q_ = q; p = std :: min (p, q_); return ;}
template < class T, class I > void chkmax (T &p, I q) {T q_ = q; p = std :: max (p, q_); return ;}
void solve () {
  int n, mn = 2e9, mx = -2e9;
  read (n);
  while (n --) {
    int a;
    read (a);
    chkmax (mx, a);
    chkmin (mn, a);
  }
  printf ("%d\n", mx - mn);
  return ;
}
bool Med;
signed main () {
  debug ("%.8lf MB\n", (&Mbe - &Med) / 1048576.0);
  int _;
  read (_);
  while (_ --) {
    solve ();
  }
  debug ("%.8lf ms\n", 1e3 * clock () / CLOCKS_PER_SEC);
  return 0;
}
// g++ "a.cpp" -o a -std=c++14 -O2 -Wall -Wextra -Wshadow
// check! no inline! (except fastIO)

B. Sasha and the Drawing

画图可知,可以贪心的做到染前 \(2n - 2\) 个点时每个都可以添加 \(2\) 条对角线,染剩下 \(2\) 个点时仅可添加 \(1\) 条。

image

Code
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/rope>
bool Mbe;
typedef long long i64;
typedef unsigned long long u64;
typedef __int128 i128;
std :: mt19937 rnd (std :: time (0));
template < class T > T gen (const T l, const T r) {return rnd () % (r - l + 1) + l;}
const double pi = std :: acos (-1);
template < class T > inline void read (T &val) {
  T x = 0;
  bool f = false;
  char c = std :: getchar ();
  for ( ; c < '0' || c > '9' ; c = std :: getchar ()) f |= (c == '-');
  for ( ; c >= '0' && c <= '9' ; c = std :: getchar ()) x = (x << 1) + (x << 3) + (c & 15);
  val = (!f) ? (x) : (-x);
  return ;
}
#define debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
const i64 hashmod1 = 2147483579, hashmod2 = 1610612741, hashmod3 = 805306457;
template < class T, class I > void chkmin (T &p, I q) {T q_ = q; p = std :: min (p, q_); return ;}
template < class T, class I > void chkmax (T &p, I q) {T q_ = q; p = std :: max (p, q_); return ;}

bool Med;
signed main () {
  debug ("%.8lf MB\n", (&Mbe - &Med) / 1048576.0);
  int _;
  read (_);
  while (_ --) {
    int n, k;
    read (n), read (k);
    if (k <= 4 * n - 4) printf ("%d\n", (k + 1) / 2);
    else {
      if (k == 4 * n - 3) printf ("%d\n", 2 * n - 1);
      else printf ("%d\n", 2 * n);
    }
  }
  debug ("%.8lf ms\n", 1e3 * clock () / CLOCKS_PER_SEC);
  return 0;
}
// g++ "a.cpp" -o a -std=c++14 -O2 -Wall -Wextra -Wshadow
// check! no inline! (except fastIO)

C. Sasha and the Casino

Warning:如果到第 \(\symbfit{x}\) 局赢了,那么第 \(\symbfit{x + 1}\) 局及以后的所有都与 \(\symbfit{1 \sim x}\) 局的信息都没有关系。我们只需要保证有关系的区间(局)内的最低可能获利 \(\textbf{> 0}\) 即可。

赛时就寄在上面了,死活过不去样例,最后放弃 C 去做 D。

考虑第一次赢是在第 \(i(1 \leq i \leq x + 1)\) 局,设前 \(i - 1\) 次游戏 总共 下了 \(pre_{i - 1}\) 个硬币,第 \(i\) 次游戏下了 \(cur_i\) 个硬币,如果第 \(i\) 局赢,那么有:

\[k \times cur_i > pre_{i - 1} + cur_i \]

\[(k - 1) \times cur_i > pre_{i - 1} \]

因为只能下正整数个硬币,所以有:

\[(k - 1) \times cur_i \geq pre_{i - 1} + 1 \]

\[cur_i \geq \left\lceil\dfrac{pre_{i - 1} + 1}{k - 1}\right\rceil \]

\[cur_i \geq \left\lfloor\dfrac{pre_{i - 1} + 1 + k - 2}{k - 1}\right\rfloor \]

\[cur_i \geq \left\lfloor\dfrac{pre_{i - 1} + k - 1}{k - 1}\right\rfloor \]

\[cur_i \geq \left\lfloor\dfrac{pre_{i - 1}}{k - 1}\right\rfloor + 1 \]

所以有 \(cur_i = \displaystyle \left\lfloor\dfrac{pre_{i - 1}}{k - 1}\right\rfloor + 1\),进而有 \(pre_i = pre_{i - 1} + cur_i\)。特别的,\(pre_0 = 0\)

最后看 \(pre_{x + 1} \leq a\) 是否满足即可,即可不可能下注成功。

Code
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/rope>
bool Mbe;
typedef long long i64;
typedef unsigned long long u64;
typedef __int128 i128;
std :: mt19937 rnd (std :: time (0));
template < class T > T gen (const T l, const T r) {return rnd () % (r - l + 1) + l;}
const double pi = std :: acos (-1);
template < class T > inline void read (T &val) {
  T x = 0;
  bool f = false;
  char c = std :: getchar ();
  for ( ; c < '0' || c > '9' ; c = std :: getchar ()) f |= (c == '-');
  for ( ; c >= '0' && c <= '9' ; c = std :: getchar ()) x = (x << 1) + (x << 3) + (c & 15);
  val = (!f) ? (x) : (-x);
  return ;
}
#define debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
const i64 hashmod1 = 2147483579, hashmod2 = 1610612741, hashmod3 = 805306457;
template < class T, class I > void chkmin (T &p, I q) {T q_ = q; p = std :: min (p, q_); return ;}
template < class T, class I > void chkmax (T &p, I q) {T q_ = q; p = std :: max (p, q_); return ;}

void solve () {
  i64 k, x, a;
  read (k), read (x), read (a);
  i64 used = 0;
  for (int i = 1;i <= x + 1; ++ i) {
    i64 cur = used / (k - 1) + 1;
    used += cur;
    if (used > a) {
      printf ("NO\n");
      return ;
    }
  }
  printf ("YES\n");
  return ;
}
/*
new * k > new + used
new * (k - 1) > used
new * (k - 1) >= used + 1
new >= std :: ceil ((used + 1) / (k - 1))
new >= std :: floor ((used + k - 1) / (k - 1))
new >= std :: floor (used / (k - 1)) + 1
*/
bool Med;
signed main () {
  debug ("%.8lf MB\n", (&Mbe - &Med) / 1048576.0);
  int _;
  read (_);
  while (_ --) {
    solve ();
  }
  debug ("%.8lf ms\n", 1e3 * clock () / CLOCKS_PER_SEC);
  return 0;
}
// g++ "a.cpp" -o a -std=c++14 -O2 -Wall -Wextra -Wshadow
// check! no inline! (except fastIO)

D. Sasha and a Walk in the City

\(f_{u, i, j}\) 表示以 \(u\) 为根的的子树,\(i\) 代表 \(u\) 节点是否是危险的,\(j = \displaystyle \max_{v \in \text{subtree}_u}f(u, v)\) 的方案数,其中 \(f(u, v)\) 表示 \(u \to v\) 的路径上有多少个危险的点。显然 \(1 \leq u \leq n, 0 \leq i \leq 1, 0 \leq j \leq 2\)(其中 \(0 \leq j \leq 2\) 为题目要求 \(\displaystyle \max_{1 \leq u, v \leq n}f(u, v) \leq 2\))。

显然当 \(j = 0\)\(u\) 的子树内没有一个危险的点,所以 \(f_{u, 0, 0} = 1, f_{u, 1, 0} = 0\)

根据乘法原理及其组合意义,有:

\[f_{u, 0, 1} = \prod_{v \in \text{son}_u}(f_{v, 0, 0} + f_{v, 0, 1} + f_{v, 1, 1}) - \prod_{v \in \text{son}_u}f_{v, 0, 0} \]

\[f_{u, 0, 2} = \sum_{v \in \text{son}_u}(f_{v, 0, 2} + f_{v, 1, 2}) \]

\[f_{u, 1, 1} = 1 \]

\[f_{u, 1, 2} = \sum_{v \in \text{son}_u}(f_{v, 0, 1} + f_{v, 1, 1}) \]

根据转移方程写式子即可,最终答案为 \(\displaystyle \sum_{i = 0}^{1}\sum_{j = 0}^{2}f_{1, i, j}\),其中钦定根节点为 \(1\)

Code
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/rope>
bool Mbe;
typedef long long i64;
typedef unsigned long long u64;
typedef __int128 i128;
std :: mt19937 rnd (std :: time (0));
template < class T > T gen (const T l, const T r) {return rnd () % (r - l + 1) + l;}
const double pi = std :: acos (-1);
template < class T > inline void read (T &val) {
  T x = 0;
  bool f = false;
  char c = std :: getchar ();
  for ( ; c < '0' || c > '9' ; c = std :: getchar ()) f |= (c == '-');
  for ( ; c >= '0' && c <= '9' ; c = std :: getchar ()) x = (x << 1) + (x << 3) + (c & 15);
  val = (!f) ? (x) : (-x);
  return ;
}
#define debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
const i64 hashmod1 = 2147483579, hashmod2 = 1610612741, hashmod3 = 805306457;
template < class T, class I > void chkmin (T &p, I q) {T q_ = q; p = std :: min (p, q_); return ;}
template < class T, class I > void chkmax (T &p, I q) {T q_ = q; p = std :: max (p, q_); return ;}
const int N = 3e5 + 25;
const i64 mod = 998244353;
i64 pow_mod (i64 a, i64 b, i64 p) {
  i64 res = 1;
  for (i64 i = b; i > 0; i >>= 1, a = a * a % p) {
    if (i & 1) res = res * a % p;
  }
  return res;
}
int n;
std :: vector < int > g[N];
i64 f[N][2][4];
void dfs (int u, int fa) {
  for (int i = 0;i < 2; ++ i) {
    for (int j = 0;j < 4; ++ j) {
      f[u][i][j] = 0;
    }
  }
  int son = 0;
  for (auto v : g[u]) {
    if (v != fa) dfs (v, u), son ++;
  }
  if (!son) {
    f[u][0][0] = 1;
    f[u][1][1] = 1;
    return ;
  }
  i64 prod = 1;
  f[u][0][0] = 1, f[u][0][1] = 1;
  for (auto v : g[u]) {
    if (v != fa) {
      f[u][0][1] = f[u][0][1] * ((f[v][0][1] + f[v][1][1] + f[v][0][0]) % mod) % mod;
      prod = prod * f[v][0][0] % mod;
    }
  }
  f[u][0][1] = (f[u][0][1] + mod - prod) % mod;
  f[u][0][2] = 0;
  for (auto v : g[u]) {
    if (v != fa) {
      f[u][0][2] = (f[u][0][2] + f[v][0][2] + f[v][1][2]) % mod;
    }
  }
  f[u][1][1] = 1;
  for (auto v : g[u]) {
    if (v != fa) {
      f[u][1][2] = (f[u][1][2] + f[v][0][1] + f[v][1][1]) % mod;
    }
  }
  return ;
}
void solve () {
  read (n);
  for (int i = 1;i <= n; ++ i) g[i].clear ();
  for (int i = 1;i < n; ++ i) {
    int u, v;
    read (u), read (v);
    g[u].push_back (v);
    g[v].push_back (u);
  }
  dfs (1, 0);
  i64 ans = 0;
  // for (int i = 1;i <= n; ++ i) {
  //   for (int j = 0;j < 2; ++ j) {
  //     for (int k = 0;k <= 2; ++ k) {
  //       debug ("f[%d][%d][%d] = %lld\n", i, j, k, f[i][j][k]);
  //     }
  //   }
  // }
  for (int i = 0;i < 2; ++ i) {
    for (int j = 0;j <= 2; ++ j) {
      ans = (ans + f[1][i][j]) % mod;
    }
  }
  printf ("%lld\n", ans);
  return ;
}
bool Med;
signed main () {
  debug ("%.8lf MB\n", (&Mbe - &Med) / 1048576.0);
  int _;
  read (_);
  while (_ --) {
    solve ();
  }
  debug ("%.8lf ms\n", 1e3 * clock () / CLOCKS_PER_SEC);
  return 0;
}
// g++ "a.cpp" -o a -std=c++14 -O2 -Wall -Wextra -Wshadow
// check! no inline! (except fastIO)

E. Sasha and the Happy Tree Cutting

设加第 \(i(1 \leq i \leq n - 1)\) 条边可以覆盖的链集合为 \(S_i\),那么考虑 SOSDP:设 \(f_{T}\) 表示至少需要染 \(f_{T}\) 条边才能覆盖集合 \(T\) 内的链。有显然的转移:

\[f_{T \cup S_i} \leftarrow f_{T} + 1(T \subset \{1, 2, \dots, k\}, 1 \leq i \leq n - 1) \]

现在考虑 \(S_{1 \sim n - 1}\) 的求法。考虑对于每一条链 \((a, b)\),设这是第 \(i\) 条链,那么链上的每一条边对应的 \(S\) 值都应该对 \(\{i\}\) 取并集。这个可以状态压缩 + 树上差分解决。

现在考虑一个问题,时间复杂度。本质不同\(S\) 值有多少个?因为我们只关心 \(a_1, a_2, \dots, a_k, b_1, b_2, \dots, b_k\)\(2k\) 个点,所以考虑对这 \(2k\) 个点建立虚树,这个虚树才是我们所关心的,而虚树上有 \(O(k)\) 条边,所以本质不同的 \(S\) 值只有 \(O(k)\) 个。

算上预处理倍增数组和求 LCA 的时间,时间复杂度为 \(O((n + k) \log n + 2^k \times k)\)

Code
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/rope>
bool Mbe;
typedef long long i64;
typedef unsigned long long u64;
typedef __int128 i128;
std :: mt19937 rnd (std :: time (0));
template < class T > T gen (const T l, const T r) {return rnd () % (r - l + 1) + l;}
const double pi = std :: acos (-1);
template < class T > inline void read (T &val) {
  T x = 0;
  bool f = false;
  char c = std :: getchar ();
  for ( ; c < '0' || c > '9' ; c = std :: getchar ()) f |= (c == '-');
  for ( ; c >= '0' && c <= '9' ; c = std :: getchar ()) x = (x << 1) + (x << 3) + (c & 15);
  val = (!f) ? (x) : (-x);
  return ;
}
#define debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
const i64 hashmod1 = 2147483579, hashmod2 = 1610612741, hashmod3 = 805306457;
template < class T, class I > void chkmin (T &p, I q) {T q_ = q; p = std :: min (p, q_); return ;}
template < class T, class I > void chkmax (T &p, I q) {T q_ = q; p = std :: max (p, q_); return ;}
const int N = 1e5 + 25;
int n, k, anc[21][N], dep[N];
std :: vector < int > g[N];
void dfs (int u, int fa) {
  anc[0][u] = fa, dep[u] = dep[fa] + 1;
  for (auto v : g[u]) {
    if (v != fa) dfs (v, u);
  }
  return ;
}
bool ok[1 << 20];
int f[1 << 20];
int LCA (int u, int v) {
  if (dep[u] < dep[v]) std :: swap (u, v);
  for (int i = 20;i >= 0; -- i) {
    if (dep[anc[i][u]] >= dep[v]) u = anc[i][u];
  }
  if (u == v) return u;
  for (int i = 20;i >= 0; -- i) {
    if (anc[i][u] != anc[i][v]) u = anc[i][u], v = anc[i][v];
  }
  return anc[0][u];
}
int w[N];
void update (int u, int v, int val) {
  int z = LCA (u, v);
  w[u] += val;
  w[v] += val;
  w[z] -= val;
  if (anc[0][z]) w[anc[0][z]] -= val;
  return ;
}
void dfs2 (int u, int fa) {
  for (auto v : g[u]) {
    if (v != fa) {
      dfs2 (v, u);
      w[u] += w[v];
    }
  }
  return ;
}
void solve () {
  read (n);
  for (int i = 1;i <= n; ++ i) g[i].clear ();
  for (int i = 1;i < n; ++ i) {
    int u, v;
    read (u), read (v);
    g[u].push_back (v);
    g[v].push_back (u);
  }
  dfs (1, 0);
  for (int i = 1;i < 21; ++ i) {
    for (int u = 1;u <= n; ++ u) {
      anc[i][u] = anc[i - 1][anc[i - 1][u]];
    }
  }
  for (int i = 1;i <= n; ++ i) w[i] = 0;
  read (k);
  for (int i = 0;i < k; ++ i) {
    int u, v;
    read (u), read (v);
    int z = LCA (u, v);
    update (u, v, (1 << i));
    update (z, z, -(1 << i));
  }
  dfs2 (1, 0);
  for (int i = 0;i < (1 << k); ++ i) ok[i] = false;
  std :: vector < int > vc;
  vc.clear ();
  for (int i = 2;i <= n; ++ i) {
    if (w[i] && !ok[w[i]]) ok[w[i]] = true, vc.push_back (w[i]);
  }
  f[0] = 0;
  for (int i = 1;i < (1 << k); ++ i) f[i] = 1e9;
  for (int i = 0;i < (1 << k) - 1; ++ i) {
    for (auto s : vc) {
      chkmin (f[i | s], f[i] + 1);
    }
  }
  printf ("%d\n", f[(1 << k) - 1]);
  return ;
}
bool Med;
signed main () {
  debug ("%.8lf MB\n", (&Mbe - &Med) / 1048576.0);
  int _;
  read (_);
  while (_ --) {
    solve ();
  }
  debug ("%.8lf ms\n", 1e3 * clock () / CLOCKS_PER_SEC);
  return 0;
}
// g++ "a.cpp" -o a -std=c++14 -O2 -Wall -Wextra -Wshadow
// check! no inline! (except fastIO)

F. Sasha and the Wedding Binary Search Tree

考虑 \(n\) 个点的相对顺序(对,我从这一步就没有想到),可以 dfs 遍历将 \(val\) 从小到大(按照 BST 的性质)排列起来。

可以这么干:

void dfs (int u) {
  if (son[u][0] != -1) dfs (son[u][0]);
  a[++ cnt] = val[u];
  if (son[u][1] != -1) dfs (son[u][1]);
  return ;
}

下设 \(a\) 为将 \(val\) 按 BST 的理论值从小到大 排列好的数组。

现在对于每一个值为 \(-1\) 的连续段 \([l, r]\),考虑填充其值的方案数,而答案就是这些方案数的乘积。设 \(L = a_{l - 1}\)(若 \(l = 1\)\(L = 1\)),\(R = a_{r + 1}\)(若 \(r = n\)\(R = C\))。考虑映射,可以将 \((a_l, a_{l + 1}, \dots, a_r)\) 映射为 \((a_l - L, a_{l + 1} - a_l, a_{l + 2} - a_{l + 1}, \dots, a_{r} - a_{r - 1}, R - a_{r})\),这样映射完之后的值设为 \((b_{1}, b_{2}, \dots, b_{r - l + 2})\)\(\symbfit{b}\) 满足以下性质即可推出唯一且满足条件的 \(\symbfit{(a_l, a_{l + 1}, \dots, a_r)}\)

  • 对于所有的 \(1 \leq i \leq r - l + 2\),有 \(b_i \geq 0\)
  • \(\displaystyle \sum_{i = 1}^{r - l + 2}b_i = R - L\)

现在考虑将 \(b\) 的每一个数都加 \(1\),然后使用插板法,相当于在 \(R - L + r - l + 1\) 个空内插入 \(r - l + 1\) 个板子,方案数即为 \(\dbinom{R - L + r - l + 1}{r - l + 1}\)

注:组合数可以用 \(\symbfit{\dbinom{n}{k} = \dfrac{\displaystyle \prod_{i = n - k + 1}^{n}i}{k!}}\) 的公式计算。

Code
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/rope>
bool Mbe;
typedef long long i64;
typedef unsigned long long u64;
typedef __int128 i128;
std :: mt19937 rnd (std :: time (0));
template < class T > T gen (const T l, const T r) {return rnd () % (r - l + 1) + l;}
const double pi = std :: acos (-1);
template < class T > inline void read (T &val) {
  T x = 0;
  bool f = false;
  char c = std :: getchar ();
  for ( ; c < '0' || c > '9' ; c = std :: getchar ()) f |= (c == '-');
  for ( ; c >= '0' && c <= '9' ; c = std :: getchar ()) x = (x << 1) + (x << 3) + (c & 15);
  val = (!f) ? (x) : (-x);
  return ;
}
#define debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
const i64 hashmod1 = 2147483579, hashmod2 = 1610612741, hashmod3 = 805306457;
template < class T, class I > void chkmin (T &p, I q) {T q_ = q; p = std :: min (p, q_); return ;}
template < class T, class I > void chkmax (T &p, I q) {T q_ = q; p = std :: max (p, q_); return ;}
const int N = 5e5 + 25;
const i64 mod = 998244353;
i64 pow_mod (i64 a, i64 b, i64 p) {
  i64 res = 1;
  for (i64 i = b; i > 0; i >>= 1, a = a * a % p) {
    if (i & 1) res = res * a % p;
  }
  return res;
}
i64 comb (i64 n, i64 m) {
  if (n < 0 || m < 0 || n < m) return 0;
  i64 ans = 1, fac = 1;
  for (i64 i = n;i >= n - m + 1; -- i) ans = ans * (i % mod) % mod;
  for (i64 i = 1;i <= m; ++ i) fac = fac * (i % mod) % mod;
  ans = ans * pow_mod (fac, mod - 2, mod) % mod;
  // assert (ans >= 0);
  return ans;
}
i64 query (i64 sum, i64 cnt) {return comb (sum + cnt - 1, cnt - 1);}
i64 a[N], val[N];
int son[N][2], cnt;
void dfs (int u) {
  if (son[u][0] != -1) dfs (son[u][0]);
  a[++ cnt] = val[u];
  if (son[u][1] != -1) dfs (son[u][1]);
  return ;
}
void solve () {
  int n;
  i64 c;
  read (n), read (c);
  cnt = 0;
  for (int i = 1;i <= n; ++ i) read (son[i][0]), read (son[i][1]), read (val[i]);
  dfs (1);
  std :: vector < std :: pair < int, int > > st;
  st.clear ();
  a[0] = 0;
  for (int i = 1;i <= n; ++ i) {
    if (a[i] == -1) {
      if (a[i - 1] != -1) st.push_back (std :: make_pair (i, i));
      else {
        auto &tmp = st.back ();
        tmp.second = i;
      }
    }
  }
  bool ok = true;
  i64 las = -1;
  for (int i = 1;i < n; ++ i) {
    if (a[i] != -1) {
      ok &= (las <= a[i]);
      las = a[i];
    }
  }
  if (!ok) {
    printf ("0\n");
    return ;
  }
  i64 ans = 1;
  for (auto rangeqwq : st) {
    int l = rangeqwq.first;
    int r = rangeqwq.second;
    i64 L = (l == 1) ? 1 : a[l - 1];
    i64 R = (r == n) ? c : a[r + 1];
    i64 tot = 1ll * (r - l + 2);
    ans = ans * query (R - L, tot) % mod;
  }
  printf ("%lld\n", ans);
  return ;
}
bool Med;
signed main () {
  debug ("%.8lf MB\n", (&Mbe - &Med) / 1048576.0);
  int _;
  read (_);
  while (_ --) {
    solve ();
  }
  debug ("%.8lf ms\n", 1e3 * clock () / CLOCKS_PER_SEC);
  return 0;
}
// g++ "a.cpp" -o a -std=c++14 -O2 -Wall -Wextra -Wshadow
// check! no inline! (except fastIO)
posted @ 2024-02-16 16:02  CountingGroup  阅读(30)  评论(0编辑  收藏  举报