\(\text{Problem}\)

大概就是给出 \(n\) 个数和 \(m\),要从中选最多的数使得两两异或值大于等于 \(m\)

输出方案

\(\text{Solution}\)

一开始的想法很复杂、、、

其实用到一个结论就做好了

对于一个升序数列,它们两两间的异或最小值就是相邻数的异或最小值

于是可以先排序,再 \(DP\)

设 \(f_i\) 表示到第 \(i\) 位强制选 \(i\) 能选出最多的数的数量

那么 \(f_i = f_{j} + 1(1\le j < i,a_j \oplus a_i \ge m)\)

于是优化这个 \(O(n^2)\) 的 \(DP\) 即可

这就是个很简单的事

考虑 \(j\) 的选取

若 \(a_i \oplus a_j > m\),那么异或值从高位到低位一部分等于 \(m\),然后在某一位大于 \(m\)

那么我们从高到低枚举位数,考虑在这一位之前等于 \(m\),统计这一位大于 \(m\) 的贡献

讨论 \(m\) 和 \(a_i\) 这一位的 \(0/1\) 值,发现可行数值区间是连续的,权值线段树即可

最后再处理 \(a_i \oplus a_j = m\) 的贡献

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#include <algorithm>
#define RE register
#define IN inline
using namespace std;
typedef long long LL; const int N = 3e5 + 5;
int n, m, f[N], g[N], Len, size, rt;
struct node{int v, id;}a[N];
IN bool cmp(node a, node b){return a.v < b.v;} int seg[N * 31], ls[N * 31], rs[N * 31];
void Modify(int &p, int l, int r, int x, int v)
{
if (!p) p = ++size;
if (l == r) return seg[p] = v, void();
int mid = l + r >> 1;
if (x <= mid) Modify(ls[p], l, mid, x, v);
else Modify(rs[p], mid + 1, r, x, v);
if (f[seg[ls[p]]] > f[seg[rs[p]]]) seg[p] = seg[ls[p]];
else seg[p] = seg[rs[p]];
}
int Query(int p, int l, int r, int x, int y)
{
if (x > r || y < l) return 0;
if (x <= l && r <= y) return seg[p];
int mid = l + r >> 1, L = 0, R = 0;
if (ls[p] && x <= mid) L = Query(ls[p], l, mid, x, y);
if (rs[p] && y > mid)
{
R = Query(rs[p], mid + 1, r, x, y);
if (!L) L = R;
else{
if (f[L] > f[R]) return L;
return R;
}
}
return L;
} int main()
{
scanf("%d%d", &n, &m);
for(RE int i = 1; i <= n; i++) scanf("%d", &a[i].v), a[i].id = i;
sort(a + 1, a + n + 1, cmp), Len = a[n].v;
int ans = 1, pos = 0, pre, cur;
for(RE int i = 1; i <= n; i++)
{
f[i] = 1, pre = 0;
for(RE int j = 30; j >= 0; j--)
{
if ((m >> j) & 1){if (!((a[i].v >> j) & 1)) pre |= (1 << j);}
else{
if ((a[i].v >> j) & 1)
{
cur = Query(rt, 0, Len, pre, pre + (1 << j) - 1), pre |= (1 << j);
if (f[cur] + 1 > f[i]) f[i] = f[cur] + 1, g[i] = cur;
}
else{
cur = Query(rt, 0, Len, pre + (1 << j), (LL)pre + (1LL << j + 1) - 1);
if (f[cur] + 1 > f[i]) f[i] = f[cur] + 1, g[i] = cur;
}
}
if (!j)
{
cur = Query(rt, 0, Len, pre, pre);
if (f[cur] + 1 > f[i]) f[i] = f[cur] + 1, g[i] = cur;
}
}
if (ans < f[i]) ans = f[i], pos = i;
if (i < n) Modify(rt, 0, Len, a[i].v, i);
}
printf("%d\n", (ans == 1) ? -1 : ans);
if (ans > 1) while (pos) printf("%d ", a[pos].id), pos = g[pos];
}

CF1625D.Binary Spiders的更多相关文章

  1. CF1625D - Binary Spiders[trie树优化dp]

    官方题解 题意:给数列a[],选择尽量多的数满足任意两个异或起来<=k 1625D - Binary Spiders 思路:首先,将数列排序得到,然后升序取得的值的任意两个最小值为相邻两个异或的 ...

  2. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  3. ILJMALL project过程中遇到Fragment嵌套问题:IllegalArgumentException: Binary XML file line #23: Duplicate id

    出现场景:当点击"分类"再返回"首页"时,发生error退出   BUG描述:Caused by: java.lang.IllegalArgumentExcep ...

  4. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  5. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  6. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  7. Leetcode: Convert sorted list to binary search tree (No. 109)

    Sept. 22, 2015 学一道算法题, 经常回顾一下. 第二次重温, 决定增加一些图片, 帮助自己记忆. 在网上找他人的资料, 不如自己动手. 把从底向上树的算法搞通俗一些. 先做一个例子: 9 ...

  8. Leetcode, construct binary tree from inorder and post order traversal

    Sept. 13, 2015 Spent more than a few hours to work on the leetcode problem, and my favorite blogs ab ...

  9. [LeetCode] Binary Watch 二进制表

    A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom ...

  10. [LeetCode] Find Leaves of Binary Tree 找二叉树的叶节点

    Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...

随机推荐

  1. kettel

    下载教程:(目前最高版本7.1) 1.网址:https://community.hitachivantara.com/docs/DOC-1009855 2.

  2. 学生管理系统Python

    student1=[ {1:'lucy','age':17,'sex':'n','Pnum':1111111}, {2:'tom','age':17,'sex':'m','Pnum':2222222} ...

  3. android nativate 动态注册 静态注册

    说明:在java函数的入口比较容易分析, 把activity的生命周期或者关键函数通过放在so层,分析起来就困难多了 1.在MainActivity中 package com.demo.nativat ...

  4. keepalived 主备使用

    keepalived 主备使用 本篇主要介绍一下 keepalived 的基本的 主备使用 1.概述 什么是 keepalived呢,它是一个集群管理中 保证集群高可用的软件,防止单点故障,keepa ...

  5. windows通过sshfs挂载linux目录

    之前讲过一种方法,PC跟VM在同局域网的情况下,可以用samba的方式挂载linux系统的目录到windows上.但是当PC跟VM不同局域网时这种方式就没办法了. 网络环境 在示意图中,PC只能直连物 ...

  6. 【转载】MSSQL汉字首字母查询处理自定义函数

    -- 汉字首字母查询处理用户定义函数 CREATE FUNCTION f_GetPY(@str nvarchar(4000)) RETURNS nvarchar(4000) AS BEGIN DECL ...

  7. 用Dockerfile制作一个java应用镜像,ubuntu基础篇

    内容介绍: (1) 本章目的,将一个自行开发的java程序webpay-api,制作为docker自定义镜像,并且进行部署. (2) 实验环境: 物理机:VMware 虚拟机 + CentOS 7.8 ...

  8. 自研ORM Include拆分查询(递归算法 支持无限层级) 性能优化探讨

    最近我在优化 Include 拆分查询,贴出源码供大家交流探讨是否还有优化空间. 测试代码 1 Console.WriteLine($"总记录数:{db.Query<Category& ...

  9. Python实现k-近邻算法案例学习

    一.介绍 你好,我是悦创. 博客首发:https://bornforthis.cn/column/Machine-learning/informal-essay/01.html 本文是由给私教学员 c ...

  10. python进阶之路5之流程控制(垃圾回收机制)

    垃圾回收机制 """ 有一些语言,内存空间的申请和释放都需要程序员自己写代码才可以完成 但是python却不需要 通过垃圾回收机制自动管理 ""&qu ...