首页 > 其他分享 >YC307B [ 20240625 CQYC省选模拟赛 T2 ] 一个题(ynoi)

YC307B [ 20240625 CQYC省选模拟赛 T2 ] 一个题(ynoi)

时间:2024-07-02 21:42:10浏览次数:1  
标签:省选 siz T2 YC307B int arc nex isl include

题意

你需要维护一个可重集 \(S\),支持插入删除以及查询最大的方案使得给定正整数 \(k\),划分为 \(k\) 个非空子集的按位与结果之和最大。

\(n \le 10 ^ 5\)

Sol

先上个 trie。

然后考虑一次查询怎么搞。

先转化一下,如果需要划分为 \(k\) 个子集,显然需要合并 \(n - k\) 次。

我们只需要保证每次划分操作不劣即可。

从高位到低位考虑每一位,显然只需要考虑当前位最大即可。

注意到每次合两堆只有几种情况,显然 \(0\) 与 \(0\) 合一定不劣。

因为你如果合别的,一定会少 \(1\)。

所以考虑找出当前位是 \(0\) 的数字个数,直接判断和当前需要合的个数 \(k'\) 即可。

若当前可以用 \(0\) 合光就直接合掉,这样剩下一定会最优,直接递归到下一层 \(1\) 即可。

而没法合完的情况怎么办呢,你考虑先把所有 \(0\) 合起来,然后用个 \(\text{set}\) 把这个东西存下来。

这样你存起来的数只会有 \(\log\) 个,因为你在走 \(1\) 的子树时,有可能可以把别的数字合过来,所以要存一下。

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

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <set>
#include <vector>
#include <unordered_set>
#define int long long
using namespace std;
#ifdef ONLINE_JUDGE

/* #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++) */
/* char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf; */

#endif
int read() {
    int p = 0, flg = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') flg = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        p = p * 10 + c - '0';
        c = getchar();
    }
    return p * flg;
}
void write(int x) {
    if (x < 0) {
        x = -x;
        putchar('-');
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}
bool _stmer;

const int N = 1e5 + 5, inf = (1 << 30) - 1;

array <int, N * 33> edge, isl, siz, fa;
array <array <int, 2>, N * 33> nex;

int cnt = 1;

void pushup(int x) {
    x = fa[x];
    while (x) {
        siz[x] = siz[nex[x][0]] + siz[nex[x][1]];
        isl[x] = isl[nex[x][0]] & isl[nex[x][1]];
        edge[x] = edge[nex[x][0]] + edge[nex[x][1]];
        x = fa[x];
    }
}

void insert(int x) {
    int p = 1;
    for (int i = 30; ~i; i--) {
        if (!nex[p][x >> i & 1])
            cnt++, fa[cnt] = p, nex[p][x >> i & 1] = cnt;
        p = nex[p][x >> i & 1];
    }
    siz[p]++, isl[p] = x, edge[p] += x;
    pushup(p);
}

void delet(int x) {
    int p = 1;
    for (int i = 30; ~i; i--)
        p = nex[p][x >> i & 1];
    siz[p]--, isl[p] = siz[p] ? (bool)siz[p] * x : inf, edge[p] -= x;
    pushup(p);
}

int query(int k) {
    multiset <int> arc;
    k = siz[1] - k;
    /* cerr << k << endl; */
    int p = 1, ans = 0;
    for (int i = 30; ~i; i--) {
        int tp = siz[nex[p][0]] - 1;
        for (auto t : arc)
            if ((t >> i & 1) ^ 1) tp++;
        if (!~tp) { p = nex[p][1]; continue; }
        if (tp > k) {
            int res = edge[nex[p][1]];
            unordered_set <int> tp0;
            for (auto t : arc)
                if (t >> i & 1) res += t, tp0.insert(t);
            for (auto t : tp0) arc.erase(t);
            ans += res, p = nex[p][0];
        }
        else {
            k -= tp;
            int res = isl[nex[p][0]];
            /* cerr << i << " " << p << " " << nex[p][0] << endl; */
            unordered_set <int> tp0;
            for (auto t : arc)
                if ((t >> i & 1) ^ 1) res &= t, tp0.insert(t);
            for (auto t : tp0) arc.erase(t);
            arc.insert(res), p = nex[p][1];
        }
    }
    ans += (siz[p] - k) * isl[p];
    for (auto t : arc) ans += t;
    return ans;
}

bool _edmer;
signed main() {
    cerr << (&_stmer - &_edmer) / 1024.0 / 1024.0 << "MB\n";
    int n = read(), q = read();
    isl[0] = inf;
    for (int i = 1, x; i <= n; i++)
        x = read(), insert(x);
    while (q--) {
        int op = read(), k = read();
        if (op == 1) insert(k);
        if (op == 2) delet(k);
        if (op == 3) write(query(k)), puts("");
    }
    return 0;
}

标签:省选,siz,T2,YC307B,int,arc,nex,isl,include
From: https://www.cnblogs.com/cxqghzj/p/18280599

相关文章

  • 联合省选 2024 游记
    省流:abs(__int128)纯属去体验一下。FJ-S0124,谁都比不上我八倍队线。Day1上场。看T1。这个题目背景咋和题目一点关系都没有。。。盯了一会儿发现可以把\(x,y\)加起来判断就可以了。然后花十分钟码了一个直接枚举答案的,发现答案可能很大,于是开始拆贡献。这里其实已经有想过......
  • Luogu P9542 [湖北省选模拟 2023] 棋圣 alphago
    2023.08.19:修改了一处笔误。手玩发现对于一颗生成树,如果存在至少一个点的度数\(>2\)(即不为链),那么肯定能使得所有棋子都在一条边的两个端点上。因为有度数\(>2\)的点的存在,这里就可以合并与其相连的点的棋子。先考虑非链的情况的答案,记两部分棋子黑白棋子颜色分别为\(c(a/......
  • ESP32-点亮TFT2.4电阻触摸屏 学习笔记
    1、下载好arduinoIDE开发软件IDE(IntegratedDevelopmentEnvironment),译为集成开发环境,相当于编辑器编译器加连接器+其他。ArduinoIDE就是Arduino团队提供的一款专门为Arduino设计的编程软件,使用它,我们便能将程序从代码上传至Arduino主板。去官网下载:Software|Arduino,也......
  • 阅读笔记《GB/T28449-2018信息安全技术网络安全等级保护测评过程指南》
    方案编制:测评对象确定、测评指标确定、测评内容确定、工具测试方法确定、测评指导书开发、测评方案编制对每项活动均给出相应的工作流程、主要任务、输出文档及活动中的相关方的职责的规定,每项工作任务均有相应的输入、任务描述和输出产品测评风险:影响系统正常运行、感信息泄露......
  • 【计算机毕业设计】springboot229基于Spring Boot的企业员工薪酬关系系统的设计
    传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,薪资信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的企业员工薪酬关系系统。本企业员......
  • 搭载飞腾FT2000+/64处理器全国产加固服务器
        搭载飞腾FT2000+/64,64核服务器平台的加固服务器是专为高安全性、高可靠性及能在严苛环境下稳定运行而设计的服务器产品。服务器采用国产飞腾处理器为核心,体现了自主可控的技术特点,广泛适用于政府、军事、航天等领域。   以下是我们自主研发的加固服务器的一......
  • 基于飞腾FT2000/D2000处理器国产化网安系统
        国产化网安是指基于国产软硬件构建的网络安全防护体系,从底层芯片、操作系统、数据库、中间件到上层应用软件,均采用国产自主可控的技术和产品。这样的系统旨在提高信息安全水平,确保数据和通信的保密性、完整性和可用性,同时减少对外部技术的依赖,增强国家网络空间的安......
  • IIC驱动-基于EEPROM存储芯片AT24C02模块和三合一环境传感器AP3216C
    本文将基于IIC协议编写EEPROM芯片AT24C02存储芯片的IIC驱动程序,本文内容将分为三个部分:imx6ull的IIC控制器介绍,AT24C02存储芯片介绍,IIC的Linux驱动程序编写。关于IIC协议的内容与介绍这里不展开,相关资料很多,可以自行去查阅,但是这里需要注意的是,IIC协议本身就是一个协议,只是一些基......
  • huggingface官网下载并处理ImageNet2012数据集
    文章目录一、下载imagenet2012数据集二、转换imagenet数据集格式ImageNet数据集可以直接从ImageNet官方网站获取数据,但通常需要注册并遵守使用协议。另外,由于数据集较大,往往下载需要花费大量的时间空间,而通过huggingface下载数据集的方法不仅速度相对较快,而且能够直......
  • Day28.property使用part2
    1.property使用part2_多次调用类中的函数方法property用法,案例一代码如下:'''案例一'''classPeople:def__init__(self,name):self.__name=namedefget_name(self):returnself.__namedefset_name(self,val):......