\(\mathcal{Description}\)

  给定排列 \(\{a_n\}\),求字典序第 \(K\) 大的合法排列 \(\{b_n\}\)。称一个排列 \(\{p_n\}\) 合法,当且仅当依次将 \([1,m],[2,m+1],\cdots,[n-m+1,n]\) 内的 \(p\) 升序排列后,得到的排列为 \(\{a_n\}\) 相同。

  \(n\le2 \times 10^6\),\(m\le 100\),\(K\le2 \times 10^{16}\) 。

\(\mathcal{Solution}\)

  应该说是构造题吧,想到几乎所有结论却打不出分 qwq。

  显然,\(b_i\) 在 \(\{a_n\}\) 中的下标属于集合 \([\max\{1,i-m+1\},n]\),反过来,\(a_i\) 在 \(\{b_n\}\) 中对应的下标属于集合 \([1,\min\{i+m-1,n\}]\)。

  然后可以发现 \(\{a_n\}\) 中的逆序对非常特殊。有性质:

\[ (\exists j\in[1,i))(a_i<a_j) \Rightarrow b_{i+m-1}=a_i
\]

  归纳证明。考虑一对 \((i,j)\),满足 \(\max_{k\in(i,j)}\{a_k\}<a_j<a_i\),若 \(i+1=j\),显然;否则对于 \(k\in(i,j)\),已有 \(b_{k+m-1}=a_k\),不妨设 \(b_x=a_j\),则 \(x\not\in[i+m,j+m-2]\),而 \(x\in[1,\min\{j+m-1,n\}]\),又有 \(x\ge i+m\),所以 \(x=j+m-1\) 成立。

  所以可以直接确定所有存在逆序对的 \(j\) 的位置。接下来考虑 \(\{a_n\}\) 是一个单增排列的情况。

  从左往右构造 \(\{b_n\}\),我们需要求出固定 \(\{b_n\}\) 的前缀时所有合法 \(\{b_n\}\) 的方案数。不妨设固定前 \(i\) 位,对于一个没有出现的 \(a_j\),其放置方案数显然为 \(\min\{j+m-1,n\}-i\)。乘法原理就可以得到所求,最后类似多叉树求第 \(K\) 大地枚举就好,复杂度 \(\mathcal O(n^3)\)。

  由于方案数是指数增长,所以前面很多位直接从小到达钦定,再对后缀的 \(\mathcal O(\log_mn)\) 暴力构造即可。

  复杂度 \(\mathcal O(n+\log^3n)\)。

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>
#include <algorithm> typedef long long LL; inline LL rint () {
LL x = 0; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () );
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x;
} template<typename Tp>
inline void wint ( Tp x ) {
if ( x < 0 ) putchar ( '-' ), x = ~ x + 1;
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
} inline int min_ ( const int a, const int b ) { return a < b ? a : b; } const int MAXN = 2e6;
int n, m, a[MAXN + 5];
LL K;
int top, stk[MAXN + 5], ans[MAXN + 5];
bool used[MAXN + 5]; inline void setnxt ( int& pos, const int x ) { for ( ; ans[pos]; ++ pos ); ans[pos] = x; } int main () {
freopen ( "gift.in", "r", stdin );
freopen ( "gift.out", "w", stdout );
n = rint (), m = rint (), K = rint ();
for ( int i = 1; i <= n; ++ i ) a[i] = rint ();
for ( int i = 1; i <= n; ++ i ) {
if ( a[i] < a[stk[top]] ) ans[i + m - 1] = a[i];
else stk[++ top] = i;
}
int mut = top, pos = 1;
for ( LL all = 1; mut && all < K; -- mut ) {
all *= min_ ( m, top - mut + 2 );
}
for ( int i = 1; i < mut; ++ i ) setnxt ( pos, a[stk[i]] );
for ( int i = mut; i <= top; ++ i ) {
for ( int j = mut; j <= top; ++ j ) {
if ( used[j] ) continue;
used[j] = true;
LL all = 1;
for ( int k = mut, pre = i; k <= top; ++ k ) {
if ( !used[k] ) {
all *= min_ ( top, k + m - 1 ) - pre ++;
}
}
if ( all < K ) K -= all, used[j] = false;
else { setnxt ( pos, a[stk[j]] ); break; }
}
}
for ( int i = 1; i <= n; ++ i ) {
wint ( ans[i] );
putchar ( i ^ n ? ' ' : '\n' );
}
return 0;
}

Solution -「LOCAL」「cov. 牛客多校 2020 第三场 I」礼物的更多相关文章

  1. Solution -「LOCAL」「cov. 牛客多校 2020 第五场 C」Easy

    \(\mathcal{Description}\)   Link.(完全一致)   给定 \(n,m,k\),对于两个长度为 \(k\) 的满足 \(\left(\sum_{i=0}^ka_i=n\r ...

  2. 2019牛客多校训练第三场H.Magic Line(思维)

    题目传送门 大致题意: 输入测试用例个数T,输入点的个数n(n为偶数),再分别输入n个不同的点的坐标,要求输出四个整数x1,y1,x2,y2,表示有一条经过点(x1,y1),(x2,y2)的直线将该二 ...

  3. 2019牛客多校训练第三场B.Crazy Binary String(思维+前缀和)

    题目传送门 大致题意: 输入整数n(1<=n<=100000),再输入由n个0或1组成的字符串,求该字符串中满足1和0个数相等的最长子串.子序列. sample input: 801001 ...

  4. 牛客多校对抗第6场 A Singing Contest

    [20分]标题:A.Singing Contest | 时间限制:1秒 | 内存限制:256MJigglypuff is holding a singing contest. There are 2n ...

  5. 牛客多校训练第八场C.CDMA(思维+构造)

    题目传送门 题意: 输入整数m( m∈2k ∣ k=1,2,⋯,10),构造一个由1和-1组成的m×m矩阵,要求对于任意两个不同的行的内积为0. 题解: Code: #include<bits/ ...

  6. 牛客多校训练第八场G.Gemstones(栈模拟)

    题目传送门 题意: 输入一段字符串,字符串中连续的三个相同的字符可以消去,消去后剩下的左右两段字符串拼接,求最多可消去次数. 输入:ATCCCTTG   输出:2 ATCCCTTG(消去CCC)——& ...

  7. 2019牛客多校训练第四场K.number(思维)

    题目传送门 题意: 输入一个只包含数字的字符串,求出是300的倍数的子串的个数(不同位置的0.00.000等都算,并考虑前导零的情况). sample input: 600 1230003210132 ...

  8. 2019暑假牛客多校训练-第八场-C-CDMA(递归、水题)

    观察前3组可以推出递归规律,生成下一个类型时,每行copy自身与自身相反. 题目描述 Gromah and LZR have entered the third level. There is a b ...

  9. 2018年牛客多校寒假 第四场 F (call to your teacher) (图的连通性)

    题目链接 传送门:https://ac.nowcoder.com/acm/contest/76/F 思路: 题目的意思就是判断图的连通性可以用可达性矩阵来求,至于图的存储可以用邻接矩阵来储存,求出来可 ...

随机推荐

  1. Linux系统管理学习实训任务书

    1.<Linux系统管理实训任务一之搭建实验基础环境> https://www.toutiao.com/i6763578305091207694/ 2.<Linux系统管理实训任务一 ...

  2. javascript实现数字整数位每三位一个逗号分隔

    Number(1234567).toLocaleString(); //结果"1,234,567" Number(123456789).toLocaleString()//结果&q ...

  3. FIS本地发布-其他同事通过IP访问

    方法很简单,只需在fis的配置文件那里进行修改即可. 文件路径在 C:\Users\Su\AppData\Roaming\npm\node_modules\fis\node_modules\fis-c ...

  4. 贝塞尔曲线(面)二三维可视化(Three+d3)

    贝塞尔曲线(面)二三维可视化(Three+d3) 在学完 games101 几何后开始实践,可视化贝塞尔曲线 我想实现三维的贝塞尔曲线,用 threejs,但是 threejs 控制太麻烦了,因此,我 ...

  5. 《剑指offer》面试题60. n个骰子的点数

    问题描述 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s.输入n,打印出s的所有可能的值出现的概率. 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i ...

  6. 《手把手教你》系列技巧篇(五十八)-java+ selenium自动化测试-分页测试(详细教程)

    1.简介 前几天,有人私信里留言问宏哥,分页怎么自动化测试了,完了给他说了说思路,不知道最后搞定没有,索性宏哥就写一篇文章来讲解和介绍如何处理分页. 2.测试场景 对分页来说,我们最感兴趣的和测试的无 ...

  7. HTML+CSS+Javascript实现轮播图效果

    HTML+CSS+Javascript实现轮播图效果 注意:根据自己图片大小来更改轮播图大小. <!doctype html> <html> <head> < ...

  8. Javascript中数组的定义和常见使用方法

    一.定义数组 1.定义数组 var arry=[1,2,'小名',false] //var 数组名=[值1,值2,...] 2.设置数组长度 arry.length=10 //数组长度设置为10 二. ...

  9. Docker 私服

    目录 什么是 Docker 私服? Docker 私服搭建 上传镜像至私服 从私服拉取镜像 什么是 Docker 私服? Docker 官方的 Docker Hub 是一个用于管理公共镜像的仓库,我们 ...

  10. deepin20搜狗输入法使用

    放大打字框 打出中文语句符号