题意:给定一个长度为 \(n\) 的序列 \(A\),\(A_i \in [0, 2 ^ k)\)。定义 \(f(x)\) 为 \(A_1\) ^ \(x\),\(A_2\) ^ \(x \cdots\) \(A_n\) ^ \(x\) 这个序列的逆序对数量。现在将 \(x \in [0, 2 ^ k)\) 按照 \(f(x)\) 为第一关键字,\(x\) 为第二关键字从小到大排序,求排名为 \(p\) 的 \(f(x)\) 及 \(x\)。

\(n \le 5 \times 10 ^ 5, 0 \le k \le 30, 1 \le p \le 2 ^ k\)


简要题解如下:

  1. 考虑点对 \((i, j)(i < j)\) 对每个 \(f(x)\) 的贡献。

  2. 不难发现,找到 \(a_i, a_j\) 最高的不相同的位置 \(u\) 那么 \(a_i, a_j\) ^ \(x\) 后的大小关系只于 \(u\) 这一位的选择有关。

  3. 若 \(a_i < a_j\) 那么当且仅当 \(u\) 这位为 \(1\) 会造成贡献;否则 \(u\) 这位为 \(0\) 会造成贡献。

  4. 注意到枚举点对是 \(\mathcal{O(n ^ 2)}\) 级别的,考虑优化这个枚举的过程。

  5. 可以发现因为本质上是点对对答案造成的贡献,可以使用类似于 \(\rm CDQ\) 分治的做法来优化这个流程。

  6. 我们将在从高往低 \(u\) 这个位上不同的数分为两个集合,因为数组是按照排列顺序来的,于是可以 \(\mathcal{O(n)}\) 地计算出这一位的贡献。然后递归处理两个集合,复杂度 \(\mathcal{O(nk)}\)。

  7. 接下来考虑一个经典转化:二分答案,统计小于小于等于 \((f(x), x)\) 的数量个数。

  8. 统计时折半搜索,然后使用双指针优化即可减小一半的指数。

复杂度 \(\mathcal{O(k2 ^ {k / 2} + nk)}\)。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, l, r) for (int i = l; i <= r; ++i)
const int N = 5e5 + 5;
const int M = 30 + 5;
struct node { int x, y;} L[(1 << (M / 2))], R[(1 << (M / 2))];
int n, k, p, lx, rx, val, a[N], f[2][M];
int read() {
char c; int x = 0, f = 1;
c = getchar();
while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
void solve(vector <int> G, int k) {
if(k < 0 || !G.size()) return ;
vector <int> L, R; int lx = 0, rx = 0;
for (int i = 0; i < G.size(); ++i) {
if((G[i] >> k) & 1) f[1][k] += lx, ++rx, R.push_back(G[i]);
else f[0][k] += rx, ++lx, L.push_back(G[i]);
}
solve(L, k - 1), solve(R, k - 1);
}
bool cmp(node a, node b) { return a.x == b.x ? a.y < b.y : a.x < b.x;}
int check(int val, int x) {
int ans = 0, j = rx;
rep(i, 1, lx) {
for (; R[j].x + L[i].x > val && j; --j) ;
for (; R[j].x + L[i].x == val && R[j].y + L[i].y > x && j; --j) ;
ans += j;
}
return ans;
}
signed main () {
freopen ("f.in", "r", stdin);
freopen ("f.out", "w", stdout);
n = read(), k = read(), p = read();
rep(i, 1, n) a[i] = read();
vector <int> G; rep(i, 1, n) G.push_back(a[i]);
solve(G, k - 1);
lx = (1 << (k / 2)), rx = (1 << (k - k / 2));
rep(i, 0, lx - 1) L[i + 1].y = i * rx;
rep(i, 0, rx - 1) R[i + 1].y = i;
rep(i, 0, lx - 1) rep(j, 0, k / 2 - 1) L[i + 1].x += f[(i >> j) & 1][j + k - k / 2];
rep(i, 0, rx - 1) rep(j, 0, k - k / 2 - 1) R[i + 1].x += f[(i >> j) & 1][j];
sort(L + 1, L + lx + 1, cmp), sort(R + 1, R + rx + 1, cmp);
int l = 0, r = n * n / 2;
while (l < r) {
int Mid = (l + r) / 2;
if(check(Mid, 1 << k) >= p) r = Mid;
else l = Mid + 1;
}
val = r, l = 0, r = (1 << k) - 1;
while (l < r) {
int Mid = (l + r) / 2;
if(check(val, Mid) >= p) r = Mid;
else l = Mid + 1;
}
printf("%lld %lld", val, r);
return 0;
}

首先发现点对对每位之间的贡献是独立的是非常重要的

其次需要意识到本质上是点对的贡献,通常使用分治解决。

注意查排名或字典序的套路:

  1. 二分答案转化为查询小于等于答案的数量个数

  2. 按位确定答案,同样转化为统计某一个前缀下后缀随意的数量

折半搜索通常解决一类选择没有关联性,两边可合并的问题,数据范围出现 \(30, 40\) 尤其要注意。

2020-11-21 f的更多相关文章

  1. apiAutoTest-更新2020/11/23

    原始版本 简书:https://www.jianshu.com/p/6bfaca87a93b 博客园:https://www.cnblogs.com/zy7y/p/13426816.html test ...

  2. 打印出1,11,21,31,41。。。。。。的shell脚本

    打印出1,11,21,31,41......的shell脚本 方法一:#!/bin/bash ;i<;i=i+));do echo $i #cat -n /etc/services | sed ...

  3. China Intelligent Office Summit(2018.11.21)

    时间:2018.11.21地点:中关村软件园国际会议中心

  4. 第33次Scrum会议(11/21)【欢迎来怼】

    一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/11/21 11:35~11:57,总计22min.地点:东北 ...

  5. 2017/11/21 Leetcode 日记

    2017/11/21 Leetcode 日记 496. Next Greater Element I You are given two arrays (without duplicates) num ...

  6. Linux编译内核 Ubuntu18.04 -2020.11.04

    Linux编译内核 Ubuntu18.04 -2020.11.04 关闭虚拟机并备份 首先关闭虚拟机,其次直接找到.vmdk所在目录,并压缩该目录实现备份 下载内核源码 Linux内核官网:https ...

  7. Goland 2020.2.x 激活码永久破解教程 (最新Goland激活码!2020.11.26亲测可用!)

    在2020.11.26 Goland的用户们又迎来了一次更新,这就导致很多软件打开时候就提示Goland激活码已经失效,码小辫第一时间给各位分享了关于最新Goland激活破解教程! goland已经更 ...

  8. 2020.11最新JAVA环境安装配置

    Windows10下java环境配置 更新:2020年11月25日 电脑环境: windows10 64位 一.下载jdk 首先到Oracle网站下载对应操作系统的jdk安装包. https://ww ...

  9. 【2020.11.28提高组模拟】T1染色(color)

    [2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...

  10. JZOJ 11.21 提高B组反思

    JZOJ 11.21 提高B组反思 T1 第二类斯特林数 直接套公式 \(S(i,j)=S(i-1,j-1)+S(i-1,j)*j\) 由于过大,\(unsigned\ long\ long\)都存不 ...

随机推荐

  1. 【计算机组成】 Quartus II 关于总线data[][]转换多个总线data[]时不成功的问题

    xjtuse 直接使用报错: 加中间层不报错:

  2. 【python】QT5 cvimg 转 pixmap

    自己乱搞了一个 import cv2 from PIL import Image imageRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) im = Image. ...

  3. Generative Adversarial Nets (GAN)

    目录 目标 框架 理论 数值实验 代码 Generative Adversarial Nets 这篇文章,引领了对抗学习的思想,更加可贵的是其中的理论证明,证明很少却直击要害. 目标 GAN,译名生成 ...

  4. 基于Java swing+mysql+eclipse的【水电费管理系统】

    本项目为前几天收费帮学妹做的一个项目,Java swing项目,在工作环境中基本使用不到,但是很多学校把这个当做编程入门的项目来做,故分享出本项目供初学者参考. CSDN9.9赞助下载: https: ...

  5. Vue.js高效前端开发 • 【Ant Design of Vue框架进阶】

    全部章节 >>>> 文章目录 一.栅格组件 1.栅格组件介绍 2.栅格组件使用 3.实践练习 二.输入组件 1.输入框组件使用 2.选择器组件使用 3.单选框组件使用 4.实践 ...

  6. Mysql 设计超市经营管理系统,包括员工库存表(stock) 和 仓库表(warehouse)

    互联网技术学院周测机试题(三) 一.需求分析 为进一步完善连锁超市经营管理,提高管理效率,减少管理成本,决定开发一套商品管理系统,用于日常的管理.本系统分为商品管理.员工管理.店铺管理,库存管理等功能 ...

  7. LDAP客户端安装

    安装环境: 10.43.159.7 客户端 使用ldap客户端验证登陆: 用户为10.43.159.9服务端上面创建的ldap:zdh1234 1.安装LDAP client认证需要的pam包 yum ...

  8. Django在使用logging日志模块时报错无法操作文件 logging error Permission Error [WinError 32]

    产生原因: 这个问题只会在开发的时候遇到,而且配置是写入到setting.py配置文件,我们定义了日志文件大小,当日志满了的时候,这时候就会遇到这个问题, 因为在使用Pycharm运行django的时 ...

  9. Python中去除字符串中的单个或多个空格的方法总结

    python中去除字符串中空格的方法比较多,单个看起来也都比较简单 但是使用起来容易发生混淆 为了加深记忆 将常用的去除字符串中空格的方法汇总如下 方法一:strip()方法 >>> ...

  10. MYSQL 自定义序列函数

    代码如下: DROP TABLE SEQNUM; -- 创建序列表 CREATE TABLE SEQNUM( ID BIGINT ); -- 插入初识值 insert INTO SEQNUM valu ...