CF 979D Kuro and GCD and XOR and SUM(异或 Trie)

给出q(<=1e5)个操作。操作分两种,一种是插入一个数u(<=1e5),另一种是给出三个数x,k,s(<=1e5),求当前所有u中满足,k|u,x+u<=s,且\(x\oplus u\)最大的u。

做法好神啊。关于异或的问题有一种常见做法,就是利用01trie来查找在一堆数里面,哪个数与x的异或值最大。这道题就是这个思路。如果去掉k必须整除v这个条件,那么就转化成了上一个问题(只不过有最大值的限制,怎么解决具体看代码)。

这道题的做法非常神奇。我们建1e5个Trie,第i个Trie中插入值为i的倍数的数。这样,查询x,k,s时,只要查询第k个Trie即可,因为里面的数一定满足k|v。插入时要遍历u的所有因数si,然后将u插入第si个Trie。

注意,异或运算是在尾部对齐的,但是要在Trie上贪心,所以必须在插入和查询的数前补零,使他们长度相同。

分析一波复杂度:

  • 预处理:我们需要预处理出u的因数。u的最大值为Max=1e5。用类似筛法的方法,时间复杂度是\(O(Max(1+\frac{1}{2}+\frac{1}{3}...+\frac{1}{Max}))=O(MaxInMax)\)。
  • 查询:就是Trie上的查询,总时间复杂度为\(O(qlog_2Max)\)。
  • 插入:一个数最多只有\(log_2(Max)\)个因数(\(2*10^9\)内因数最多的数之一是1837836000,有1536个因数),所以总的时间复杂度为\(O(qlog^2_2(Max))\)。
  • 空间复杂度:最多插入\(qlog_2(Max)\)个数,因此空间复杂度为\(qlog_2^2(Max)\)。

果然只能膜拜膜拜。

#include <cstdio>
#include <vector>
using namespace std; const int maxnum=1e5+5, maxq=1e5+5, maxn=maxq*17*17, INF=1e9;
//maxnum指插入的数的最大值 maxq指查询的最多数目
//maxn指结点的最多数目(=maxq*插入几个trie*插入数的二进制长度)
int s[maxn][2], minm[maxn], v[maxn], tot;
int q, root[maxnum], use[maxnum];
vector<int> div[maxnum]; void init(){
for (int i=1; i<maxnum; ++i)
for (int j=i; j<maxnum; j+=i)
div[j].push_back(i);
} //把x插到对应的trie里,注意维护子树中的最小数 l:处理到从左到右第几位
void insert(int &now, int x, int l){
if (!now){ now=++tot; minm[now]=INF; }
minm[now]=min(minm[now], x);
if (l==-1){ v[now]+=x; return; }
if ((x>>l)&1) insert(s[now][1], x, l-1);
else insert(s[now][0], x, l-1);
} //要找到v<=lim,并且x^v尽量大(贪心)。函数返回v
//注意由于没有删除操作,路径底下一定有点。
int query(int now, int x, int lim, int l){ //l:第几位
if (l==-1) return v[now];
int s0=s[now][0], s1=s[now][1];
if (!s0||minm[s0]>lim) return query(s[now][1], x, lim, l-1);
if (!s1||minm[s1]>lim) return query(s[now][0], x, lim, l-1);
if ((x>>l)&1) return query(s[now][0], x, lim, l-1);
else return query(s[now][1], x, lim, l-1);
} int main(){
init();
scanf("%d", &q); int op, x, k, s;
for (int i=0; i<q; ++i){
scanf("%d", &op);
if (op==1){
scanf("%d", &x);
if (use[x]) continue; use[x]=1;
for (int j=0; j<div[x].size(); ++j)
insert(root[div[x][j]], x, 18);
} else {
scanf("%d%d%d", &x, &k, &s);
if (x%k||!minm[root[k]]||minm[root[k]]+x>s) puts("-1"); //注意可能没有一个数
else printf("%d\n", query(root[k], x, s-x, 18)); //保证一定有解
}
}
return 0;
}

CF 979D Kuro and GCD and XOR and SUM(异或 Trie)的更多相关文章

  1. Codeforces 979 D. Kuro and GCD and XOR and SUM(异或和,01字典树)

    Codeforces 979 D. Kuro and GCD and XOR and SUM 题目大意:有两种操作:①给一个数v,加入数组a中②给出三个数x,k,s:从当前数组a中找出一个数u满足 u ...

  2. codeforces 979D Kuro and GCD and XOR and SUM

    题意: 给出两种操作: 1.添加一个数字x到数组. 2.给出s,x,k,从数组中找出一个数v满足gcd(x,k) % v == 0 && x + v <= s && ...

  3. CodeForces 979 D Kuro and GCD and XOR and SUM

    Kuro and GCD and XOR and SUM 题意:给你一个空数组. 然后有2个操作, 1是往这个数组里面插入某个值, 2.给你一个x, k, s.要求在数组中找到一个v,使得k|gcd( ...

  4. D. Kuro and GCD and XOR and SUM

    Kuro is currently playing an educational game about numbers. The game focuses on the greatest common ...

  5. CodeForces979D:Kuro and GCD and XOR and SUM(Trie树&指针&Xor)

    Kuro is currently playing an educational game about numbers. The game focuses on the greatest common ...

  6. cf round 482D Kuro and GCD and XOR and SUM

    题意: 开始有个空集合,现在有两种操作: $(1,x)$:给集合加一个数$x$,$x \leq 10^5$; $(2,x,k,s)$:在集合中找一个$a$,满足$a \leq s-x$,而且$k|gc ...

  7. Codeforces Round #482 (Div. 2) : Kuro and GCD and XOR and SUM (寻找最大异或值)

    题目链接:http://codeforces.com/contest/979/problem/D 参考大神博客:https://www.cnblogs.com/kickit/p/9046953.htm ...

  8. cf979d Kuro and GCD and XOR and SUM

    set做法 正解是trie-- 主要是要学会 \(a\ \mathrm{xor}\ b \leq a+b\) 这种操作 #include <iostream> #include <c ...

  9. 【Trie】【枚举约数】Codeforces Round #482 (Div. 2) D. Kuro and GCD and XOR and SUM

    题意: 给你一个空的可重集,支持以下操作: 向其中塞进一个数x(不超过100000), 询问(x,K,s):如果K不能整除x,直接输出-1.否则,问你可重集中所有是K的倍数的数之中,小于等于s-x,并 ...

随机推荐

  1. python基础-条件语句if

    if语句: if 判断条件: 执行语句 else: 执行语句 flag = Falsename = 'huipaodexiong'if name == 'python':    flag = True ...

  2. curl常用命令行总结

    curl 有时HTTP服务接口写完,需要验证下接口功能,这个使用用curl最合适了 curl 全称 command line url viewer curl www.taobao.com curl w ...

  3. poj3630 Phone List (trie树模板题)

    Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 26328   Accepted: 7938 Descr ...

  4. python中的排序函数

    1.sort() list类型有一个自带的排序函数sort() list.sort(cmp=None, key=None, reverse=False) 参数说明: (1)  cmp参数 cmp接受一 ...

  5. linux命令学习笔记(22):find 命令的参数详解

    find一些常用参数的一些常用实例和一些具体用法和注意事项. .使用name选项: 文件名选项是find命令最常用的选项,要么单独使用该选项,要么和其他选项一起使用. 可以使用某种文件名 模式来匹配文 ...

  6. 关于linux 安装 python pymssql模块

    需要先安装freetds是一个开源的C程序库,它可以实现在Linux系统下访问操作微软的SQL数据库.可以用在Sybase的db-lib或者ct-lib库,在里面也包含了一个ODBC的库.允许许多应用 ...

  7. [原]NYOJ-公约数和公倍数 -40

    大学生程序代写 //http://acm.nyist.net/JudgeOnline/problem.php?pid=40 公约数和公倍数 时间限制:1000 ms  |  内存限制:65535 KB ...

  8. 通过Jquery异步获取股票实时数据

    最近朋友让我帮他做个异步获取数据的程序,暂时服务器什么都没有,所以我就想先拿股票数据打个框架,方便后续开发和移植等事情 代码如下: <!-- 说明:股票看盘 作者:黑桃A 时间:2014-04- ...

  9. poj 1208 Web Navigation(堆栈操作)

    一.Description Standard web browsers contain features to move backward and forward among the pages re ...

  10. UML核心元素--用例

    定义:用例定义了一组用例实例,其中每个实例都是系统所执行的一些列操作,这些操作生成特定主角可以观测的值.一个完整的用例定义由参与者.前置条件.场景.后置条件构成. 1.理解用例:用例就是参与者希望通过 ...