首页 > 其他分享 >[省选联考 2024] 魔法手杖

[省选联考 2024] 魔法手杖

时间:2024-03-03 13:11:08浏览次数:21  
标签:ch min 省选 sumb 2024 int ans bit 联考

退役三年选手回来做了下~

这题直观感觉很吓人,其实看到异或就可以往 Trie 树上思考了。

这题有两个未知量 \(S\) 和 \(x\),其中 \(S\subseteq [n]\),\(x\in[0,2^k)\cap\Z\),状态过于复杂,肯定不能枚举,从答案的角度考虑。首先直观感受是有点像二分,其实我们可以从高位往低位确定答案 \(ans\)。

分析一下得出结论:\(ans\) 的二进制长度最长为 \(k+1\) 位(注意这里是个特殊情况),当且仅当 \(\sum b_i\le m\),这个时候根据贪心,取 \(x=2^k-1\) 即可,此时 \(ans=\min\{b_i\}+x\)。

否则,\(ans\) 最长为 \(k\) 位,我们可以从高往低确定 \(ans\)。假设当前正在讨论第 \(d\) 位,根据贪心,我们需要判断第 \(d\) 位是否可以为 1。假如我们把所有的 \(a_i\) 插入一棵 Trie 树,对于 \(val(S,x)=\min(\min \limits_{i \in S}(a_i+x),\min \limits_{i \in U \backslash S}(a_i \oplus x))\),我们称由 \(+\) 部分和 \(\oplus\) 部分组成。如果希望结果越大,也就是两个部分必须超过 \(ans\) 才可以。

这个时候,我们需要先确定 \(x\) 的第 \(d\) 位的取值,我们分 \(x=0\) 和 \(x=1\) 两种情况。在此基础上,\(S\) 的决策会影响 \(ans\) 的第 \(d\) 位。我们需要仔细分析一下,看一看能不能变成一个判定性问题。

假设此时在 Trie 树上的节点 \(u\),如果左右孩子都存在,当 \(x\) 取 0 时,左子树的所有值在 \(\oplus\) 部分会贡献出 \(ans=0\),右子树的所有值在 \(\oplus\) 部分会贡献出 \(ans=1\),此时我们可以考虑将左子树移到 \(+\) 部分,尝试一下 \(ans\) 变成 1。考虑下影响:\(S\) 中的最小值更新了,这里用 \(y\) 表示,那么需要满足两个条件:1、左子树的 \(b\) 的和不超过剩余值(初始值位 \(m\));2、\(+\) 部分必须超过当前的 \(ans\)(\(ans\) 未确定部分全部置成 0,\(x\) 未确定部分全部置成 1,极端情况的考虑)。只有这两个条件满足了,才能确定 \(ans\) 的第 \(d\) 位可以为 1,那么递归右子树,继续确定 \(d-1\) 位。\(x\) 取 1 时刚好对称。

所以得到了一个 贪心+dfs 的思路。先判断 \(ans\) 是否可以为 1,如果可以需要递归两种情况(合法时才递归),否则 \(ans\) 为 0,此时 \(x\) 取 0 时右子树可以忽略,递归左子树,反之亦然。也是两种情况。注意一下边界(\(d=-1\) 或者 \(u\) 是空节点)。

时间复杂度 \({\rm O}(\sum nk)\),空间复杂度 \({\rm O}(nk)\)。代码想清楚的话很好写。

由于官方数据还没出来,大样例和民间数据都过了,先占个位置。代码有问题回头再修改。

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

void read(__int128 &x){
    // read a __int128 variable
    char c; bool f = 0;
    while (((c = getchar()) < '0' || c > '9') && c != '-');
    if (c == '-') { f = 1; c = getchar(); }
    x = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') x = x * 10 + c - '0';
    if (f) x = -x;
}
void write(__int128 x){
    // print a __int128 variable
    if (x < 0) { putchar('-'); x = -x; }
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

typedef long long ll;
const int N = 1e5 + 5, K = 120 + 5;
int T, c, n, m, k, ch[N * K][2], cnt;
int b[N]; ll sumb[N * K];
__int128 a[N], mina[N * K], ans;
int nnode() {
    cnt++;
    ch[cnt][0] = ch[cnt][1] = 0;
    mina[cnt] = (__int128)1 << k;
    sumb[cnt] = 0;
    return cnt;
}
void solve(int o, int d, int t, __int128 x, __int128 y, __int128 z) {
    if (d == -1) {
        ans = max(ans, z);
        return;
    }
    __int128 bit = (__int128)1 << d, mask = bit - 1;
    if (!o) {
        ans = max(ans, y + (x | mask | bit));
        return;
    }
    int lc = ch[o][0], rc = ch[o][1];
    bool flag = false;
    if (sumb[lc] <= t && (x | mask) + min(y, mina[lc]) >= (z | bit))
        solve(rc, d - 1, t - sumb[lc], x, min(y, mina[lc]), z | bit), flag = true;
    if (sumb[rc] <= t && (x | mask | bit) + min(y, mina[rc]) >= (z | bit))
        solve(lc, d - 1, t - sumb[rc], x | bit, min(y, mina[rc]), z | bit), flag = true;
    if (flag) return;
    solve(lc, d - 1, t, x, y, z);
    solve(rc, d - 1, t, x | bit, y, z);
}
int main() {
    freopen("xor.in", "r", stdin);
    freopen("xor.out", "w", stdout);
    scanf("%d%d", &c, &T);
    while (T--) {
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 1; i <= n; i++) read(a[i]);
        for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
        cnt = 0; nnode();
        __int128 MAX = (__int128)1 << k;
        mina[0] = MAX;
        for (int i = 1; i <= n; i++) {
            int u = 1;
            sumb[u] += b[i];
            mina[u] = min(mina[u], a[i]);
            for (int j = k - 1; ~j; j--) {
                int x = a[i] >> j & 1;
                if (!ch[u][x]) ch[u][x] = nnode();
                u = ch[u][x];
                mina[u] = min(mina[u], a[i]);
                sumb[u] += b[i];
            }
        }
        ans = 0;
        if (sumb[1] <= m)
            ans = mina[1] + MAX - 1;
        else
            solve(1, k - 1, m, 0, MAX, 0);
        write(ans); putchar('\n');
    }
    return 0;
}

标签:ch,min,省选,sumb,2024,int,ans,bit,联考
From: https://www.cnblogs.com/ac-evil/p/18049859

相关文章

  • 考完省选神志不清写的考场技巧
    原本写在文本文档里的,懒得改,就发纯文字了写作思路混乱,想到什么写什么 总:先想正解再想部分再冲正解再打暴力再打部分再乱搞随机化:平面随机旋转、随机排序随机游走,序列随机排序随机染色分组,随机染色异或哈希想不出来考虑图论建模,万一图论秒了?时空卡瓶颈了?考虑......
  • 2024考研小记
    距离26日考研成绩公布已经过去了5天,每天会出现很多不同的想法,有时也会怀疑自己要不要继续坚持。想到自己也才稀里糊涂备考了4个月左右,自己取得这样的成绩也是理所应当的。没什么好难过的。随着时间的推移,毕业设计也推上了日程,整个人还是感觉到压力很大,很焦虑。但今天自己还是花......
  • 2024省选游记
    day\(-N\)(\(N\in\real\))day-1大家都喜欢day0板子练习,早晨起床回市区,拖了会儿。写了SAM,KMP,EXKMP,线段树合并,Matrixtree,Splay,tarjan,FST,调LCT时发现手感不佳。开了一把鳊鱼八十镜牢,三破剑箱强度真的幽默。最后放弃了LCT复习了一些算法,吹水,睡觉。day1最唐的一......
  • 2023-2024第一学期的助教工作总结(教务处老师助教)
    一.帮助老师整理开会后的电子版例会总结,整理各类考试试卷以及完成各类文档二.助教工作的每周时长不定,具体安排是整理电子版例会总结和整理考试试卷三.目前我自己的助教工作还处在初阶阶段,主要是帮助老师处理事情,老师平时很忙,平时帮助老师处理一些小事情,也为老师腾出时间来更......
  • 2024AcWing蓝桥杯集训·每日一题-前缀和
    1.[AcWing562.壁画]题目描述Thanh想在一面被均分为\(N\)段的墙上画一幅精美的壁画。每段墙面都有一个美观评分,这表示它的美观程度(如果它的上面有画的话)。不幸的是,由于洪水泛滥,墙体开始崩溃,所以他需要加快他的作画进度!每天Thanh可以绘制一段墙体。在第一天,他可以自由的......
  • PKUWC2024 游记
    \(\texttt{Day0}\)“空洞的”。\(\texttt{Day1}\)早上先来每日签到。那个人问我领队来不来,我说来,他就让我别签了。去礼堂找到座位后,发现他们全都已经把营员证拿了,我又从礼堂尴尬出来去签到。那个人又问我领队来不来,我直接索性不来,结果yly就在我身后。。签完就回来听开营......
  • PKUWC+WC+SCOI 2024 游记汇总
    由于是我一次性补的,有些细节可能忘掉了/lh,就不会那么详细了。题外话感觉我可能不适合写游记(?),写得没意思,主要是也没有什么动力去写。写这种东西本来应该只是为了记录,但是我好像没有这种习惯,只是为了跟风才强迫自己去写一些东西。而且看起来很像流水账。而且还可能有一种“我考得好......
  • GDOI2024游记
    Day-infCSP-S考炸了,200。Day-infNOIP一般,289。Day-infGDKOI2024,考炸了,175,差点掉出银牌。Day-infPKUWC2024,一般般,267,二等。Day-5\(\sim\)-1去高中部停课集训,四场模拟赛切了两题。Day1先说一下离谱的座位。右前方初一学弟,右后方初三学长,左后方是bamboo和另......
  • 2024AcWing蓝桥杯集训·每日一题-二分
    1.[AcWing503.借教室]题目描述在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。面对海量租借教室的信息,我们自然希望编程解决这个问题。我们需要处理接下来\(n\)天......
  • CVPR 2024 满分论文!Meta提出EfficientSAM:快速分割一切!
    前言 Meta研究者提出了一种改进思路,利用SAM的掩码图像预训练(SAMI)。这是通过利用MAE预训练方法和SAM模型实现的,以获得高质量的预训练ViT编码器。这一方法降低了SAM的复杂性,同时能够保持良好的性能。本文转载自机器之心仅用于学术分享,若侵权请联系删除欢迎关注公......