首页 > 其他分享 >[AGC064C] Erase and Divide Game 题解

[AGC064C] Erase and Divide Game 题解

时间:2024-10-08 20:37:24浏览次数:1  
标签:std AGC064C leq int 题解 trie Game bool ql

Description

Takahashi 和 Aoki 玩游戏。先在黑板上写若干个数,由 \(N\) 个互不相交的区间 \([l_i,r_i]\) 组成。

两人轮流操作,每次操作先删去所有的奇数/偶数,再把剩下的数除以 \(2\)(向下取整),无法操作的人输。

Takahashi 先手,假设两人都采用最优策略,问谁能获胜。

\(1\leq N\leq 10^4,0\leq l_i\leq r_i\leq 10^{18}\)。

Solution

首先如果总的数的个数不大,可以把每个数加到 trie 树,每次操作相当于是选择一个儿子往下走,如果没有儿子可走则输。显然可以 dp。

如果数的个数很多,可以把每个区间拆成 \(\log V\) 个形如 \(\left[x,x+2^k-1\right]\) 的区间,这些区间的在 trie 树上相当于在深度为 \(k\) 的满二叉树每个叶子下面加上同样的一条链。

然后对于每个深度 \(k\) 维护一个单独的 trie,表示接在深度为 \(k\) 的满二叉树下面的链构成的 trie。

在 trie 树上走可以看成初始有 \(\log V\) 个根,每次对于每个根同时往 \(0/1\) 方向走,如果当前每个根的子树都没有点则当前操作的人输。

此时 dp 状态改为 \(\log V\) 个树分别走到的点的位置,记忆化搜索即可。

时间复杂度:\(O(n\log^3V)\)。

Code

#include <bits/stdc++.h>

#define int int64_t

const int kMaxN = 1e4 + 5, kMaxT = kMaxN * 60 * 60;

int n, tot = 1;
int trie[kMaxT][2];
bool vis[kMaxT];
std::array<int, 60> rt;
std::map<std::array<int, 60>, bool> f;

void init() {
  f.clear();
  for (int i = 1; i <= tot; ++i)
    trie[i][0] = trie[i][1] = vis[i] = 0;
  tot = 0;
  for (int i = 0; i < 60; ++i) {
    rt[i] = ++tot;
    int lst = tot;
    for (int j = 0; j < i; ++j) {
      trie[lst][0] = trie[lst][1] = ++tot;
      lst = tot;
    }
  }
}

void ins(int cur, int x) {
  assert(cur);
  vis[cur] = 1;
  for (int i = 0; i < 60; ++i) {
    int k = (x >> i & 1);
    if (!trie[cur][k]) trie[cur][k] = ++tot;
    vis[cur = trie[cur][k]] = 1;
  }
}

void update(int l, int r, int ql, int qr) {
  if (l > qr || r < ql) return;
  else if (l >= ql && r <= qr) return ins(rt[__builtin_ctzll(r - l + 1)], l);
  int mid = (l + r) >> 1;
  update(l, mid, ql, qr), update(mid + 1, r, ql, qr);
}

bool solve(std::array<int, 60> a) {
  if (f.count(a)) return f[a];
  bool fl = 0;
  for (int i = 0; i < 60; ++i) fl |= vis[a[i]];
  if (!fl) return 0;
  bool res = 1;
  for (int o = 0; o < 2; ++o) {
    auto b = a;
    for (auto &x : b) x = trie[x][o];
    res &= solve(b);
    if (!res) break;
  }
  return f[a] = (res ^ 1);
}

void dickdreamer() {
  std::cin >> n;
  init();
  for (int i = 1; i <= n; ++i) {
    int l, r;
    std::cin >> l >> r;
    update(0, (1ll << 60) - 1, l, r);
  }
  std::cout << (solve(rt) ? "Takahashi\n" : "Aoki\n");
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:std,AGC064C,leq,int,题解,trie,Game,bool,ql
From: https://www.cnblogs.com/Scarab/p/18452475

相关文章

  • 移动端window.open跳转链接时,iOS没有反应的问题解决
    问题描述:使用window.open跳转链接时安卓可以正常跳转,但是iOS苹果上没有反应问题原因:用户交互限制iOS对于window.open的调用有严格的用户交互要求。如果window.open不是在用户交互(如点击事件)的上下文中调用的,可能会被浏览器阻止。弹出窗口拦截某些浏览器可能会默认......
  • 士兵训练 题解
    题意link.题解正解会RE几个点,是官方的栈空间太小了。再者网上几篇题解都被我hack了,好不容易找到一组hack却不是我错了,而是STD错了……所以我来写篇题解造福社会。观察到\(\max\{b_i\bmodb_j\}\),则得到的结果一定比最大值小,则最大能取到次大。那就维护一个子树......
  • 【问题解决】remote: parse error: Invalid numeric literal at line 1, column 20,解
    问题现象某同事出现过同样的推送到git仓库报错的问题,报错信息详情如下:Deltacompresionusingupto20threadsCompressingobjects:100%(4/4),done.Writingobjects:100%(5/5),521bytes|521.00KiB/s,done.Total5(delta3),reused0(delta0),pack-reused0r......
  • 系统开发基础错题解析一【软考】
    目录前言1.开发模型1.1快速原型模型优点1.2敏捷统一模型1.3增量模型的优缺点1.4极限编程1.5螺旋模型2.软件开发方法3.数据流图与数据字典3.1判定表3.2数据流图绘制3.3决策树4.概要设计和详细设计5.内聚性6.耦合性前言本文专门用来记录本人在做软考中有关系统开发基......
  • [AGC061C] First Come First Serve 题解
    Description有\(n\)个人来过,第\(i\)个人在\(a_i\)时刻来在\(b_i\)时刻走,每个人可以在来时或走时登记,问可能的登记顺序有多少种。\(n\leq5\times10^5\),\(a_i,b_i\)互不相同,\(\foralli<n,a_i<a_{i+1},b_{i}<b_{i+1}\)。Solution首先如果每个人随便选,有\(2^n\)种方......
  • [ARC112F] Die Siedler 题解
    智慧题。思路考虑第二种操作。我们会想到,我们可以先把所有牌转化成第一种牌。即:\[one=\sum_{i=1}^n\prod_{j=1}^i2^{j-1}(j-1)!c_i\]这就是第一种牌的数量。然后考虑,我们可以将第一种牌转化为第一种牌,花费的代价为:\[g=(\prod_{i=1}^n2^{i-1}(i-1)!)-1\]相当于对\(g\)......
  • P1437 [HNOI2004] 敲砖块 题解
    初拿到手感觉限制太多了,不好硬做,于是开始观察。若要取某一个数,我们要取其左上右上两个数,而这两个数又要取上面三个数,所以取一个数的前提条件其实是取这一个三角形。举例2234582712236493比如我要取第3行的6,我首先要取7和12,要取7和12,首先要取3,4,5,所以一层层拓展......
  • 鲁的女孩 题解
    题意给两个数列,对它进行排列,使得对应两数的和的最大值最小。题解贪心,先将\(a\)、\(b\)排个序(先不考虑时间)。将\(a_1\)与\(a_n\)匹配。\(a_2\)与\(a_{n-1}\)匹配。……取最大值即可。考虑到\(n\le10^5\),不可以暴力枚举。但是\(a,b\le100\),可以开一个桶,......
  • 题解 QOJ1869【Power Station of Art】/ SS241006B【结论题】
    题解QOJ1869【PowerStationofArt】/SS241006B【结论题】PetrozavodskSummer2021.Day6.XJTUContest,GPofXJTUXXIIOpenCupnamedafterE.V.Pankratiev,GrandPrixofXi'an题目描述给出一个无向图,每个点有点权\(a\)和颜色\(c\),其中颜色只会有红蓝两种。......
  • CF131C题解
    传送门:https://codeforces.com/problemset/problem/134/C关注到题目的两个限制:1.一个人只能与另外同一人交换一张卡牌。2.一个人只能交换自己原来颜色的卡牌。对于2条限制条件,显然有贪心思路:尽量让更多的人手持原有的卡牌。对于当前待交换的卡牌,一种构造思路,我们每次贪心选取......