[atARC114F]Permutation Division
由于是排列,即任意两个数字都各不相同,因此字典序最大的$q_{i}$就是将每一段的第一个数从大到小排序
接下来,考虑第一个元素,也就是每一段开头的最大值,分类讨论:
1.当$p_{1}\le k$时,取$1,2,...,k$为每一段开头是唯一一种可以使$q_{i}$以$k$为开头的方案(证明略)
2.当$p_{1}>k$时,假设这$k$个块的开头依次为$a_{1},a_{2},...,a_{k}$(其中$a_{1}=1$),将其按照开头的数字从大到小排序后,依次为$b_{1},b_{2},...,b_{k}$
考虑$a_{i}$和$b_{i}$的最长公共前缀,假设为$l$(即$\forall 1\le i\le l,a_{i}=b_{i}$且$a_{l+1}\ne b_{l+1}$),根据$b$是$a$排序得到,那么$l$还可以用另一种方式来描述:最大的$l$满足$p_{a_{1}}>p_{a_{2}}>...>p_{a_{l}}>\max_{i=l+1}^{k}p_{a_{i}}$
更进一步的,注意下面这两个性质:
1.$q_{i}$的字典序是随着$k$的减小而单调不增的,即在同样的情况下,我们希望$k$小(当$k$缩小时,只需要将任意两段合并,$q_{i}$字典序显然不增)
2.取$k=1$时即$q=p$,根据性质1即可得$q\ge p$,那么$q_{i}$最小的必要条件是其与$p_{i}$的最长公共前缀最长
继续前面的思路,不难发现$a_{l+1}-1$其实就是这一组$p_{i}$和$q_{i}$的最长公共前缀长度,而如果已经(暴力枚举)确定了$l$、$a_{l}$以及$a_{l+1}$,那么问题即变为:
选择一个长度为$l$且以1为开头、$a_{l}$为结尾的递减序列,并对$p_{a_{l+1}},p_{a_{l+1}+1},...,p_{n}$这个序列划分为$k-l$段,要求在每一段开头都小于$p_{a_{l}}$的基础上最小化字典序
当$a_{l}$确定时,我们是希望$l$尽量大的,而这个$l$也就是最长下降子序列,$o(n\log n)$预处理出来
更进一步的,在$l$和$a_{l}$确定后,我们希望$a_{l+1}$尽量大,考虑如何判定一个$a_{l+1}$是否合法,只需要满足:1.$p_{a_{l+1}}<p_{a_{l}}$;2.在$p_{a_{l+1}},p_{a_{l+1}+1},...,p_{n}$中存在$k-l$个数比$p_{a_{l}}$小
更具体的,所谓$a_{l+1}$其实就是在$p_{n}$往前,第$k-l$个比$p_{a_{l}}$小的数,那么其之后(包括其自身)恰好存在$k-l$个比$p_{a_{l}}$小的数,必然以这些数为开头,即确定了划分的方案
关于如何找到$a_{l+1}$,将1到$n$每一个数在$p_{i}$中的位置依次插入,插入时末尾第$k-l$小即为答案,用线段树维护并在其上二分即可
找到$a_{l+1}$后,实际上这最后的$k-l$个数也可以看作$p_{a_{l+1}},p_{a_{l+1}+1},...,p_{n}$中最小的$k-l$个数,那么显然我们仍然可以在$a_{l+1}$最大的情况下找到最大的$l$即可
总复杂度即$o(n\log n)$,可以通过
1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define L (k<<1)
5 #define R (L+1)
6 #define mid (l+r>>1)
7 int n,k,a[N],pos[N],dp[N],nex[N],b[N],f[N<<2];
8 void update1(int k,int l,int r,int x,int y){
9 if (l==r){
10 f[k]=y;
11 return;
12 }
13 if (x<=mid)update1(L,l,mid,x,y);
14 else update1(R,mid+1,r,x,y);
15 f[k]=max(f[L],f[R]);
16 }
17 int query1(int k,int l,int r,int x,int y){
18 if ((l>y)||(x>r))return -0x3f3f3f3f;
19 if ((x<=l)&&(r<=y))return f[k];
20 return max(query1(L,l,mid,x,y),query1(R,mid+1,r,x,y));
21 }
22 void update2(int k,int l,int r,int x){
23 f[k]++;
24 if (l==r)return;
25 if (x<=mid)update2(L,l,mid,x);
26 else update2(R,mid+1,r,x);
27 }
28 int query2(int k,int l,int r,int x){
29 if (l==r)return l;
30 if (x<=f[R])return query2(R,mid+1,r,x);
31 return query2(L,l,mid,x-f[R]);
32 }
33 int main(){
34 scanf("%d%d",&n,&k);
35 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
36 for(int i=1;i<=n;i++)pos[a[i]]=i;
37 if (a[1]<=k){
38 for(int i=k;i;i--){
39 printf("%d ",i);
40 for(int j=pos[i]+1;(j<=n)&&(a[j]>k);j++)printf("%d ",a[j]);
41 }
42 return 0;
43 }
44 memset(f,-0x3f,sizeof(f));
45 for(int i=1;i<=n;i++){
46 dp[i]=query1(1,1,n,a[i]+1,n)+1;
47 if (a[i]<=a[1])dp[i]=max(dp[i],1);
48 update1(1,1,n,a[i],dp[i]);
49 }
50 for(int i=1;i<=n;i++)
51 if (dp[i]>=k){
52 for(int j=1;j<=n;j++)printf("%d ",a[j]);
53 return 0;
54 }
55 memset(f,0,sizeof(f));
56 for(int i=1;i<=n;i++){
57 nex[pos[i]]=query2(1,1,n,k-dp[pos[i]]);
58 if (nex[pos[i]]<pos[i])nex[pos[i]]=0;
59 update2(1,1,n,pos[i]);
60 }
61 for(int i=1;i<=n;i++)nex[0]=max(nex[0],nex[i]);
62 for(int i=1;i<=n;i++)
63 if (nex[i]==nex[0])dp[0]=max(dp[0],dp[i]);
64 for(int i=1;i<nex[0];i++)printf("%d ",a[i]);
65 for(int i=nex[0];i<=n;i++)b[i-nex[0]]=a[i];
66 sort(b,b+n-nex[0]+1);
67 for(int i=k-dp[0]-1;i>=0;i--){
68 printf("%d ",b[i]);
69 for(int j=pos[b[i]]+1;(j<=n)&&(a[j]>b[k-dp[0]-1]);j++)printf("%d ",a[j]);
70 }
71 }
[atARC114F]Permutation Division的更多相关文章
- python from __future__ import division
1.在python2 中导入未来的支持的语言特征中division(精确除法),即from __future__ import division ,当我们在程序中没有导入该特征时,"/&qu ...
- Permutation Sequence
The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- [LeetCode] Evaluate Division 求除法表达式的值
Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...
- [LeetCode] Palindrome Permutation II 回文全排列之二
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...
- [LeetCode] Palindrome Permutation 回文全排列
Given a string, determine if a permutation of the string could form a palindrome. For example," ...
- [LeetCode] Permutation Sequence 序列排序
The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- [LeetCode] Next Permutation 下一个排列
Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...
- Leetcode 60. Permutation Sequence
The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- 关于分工的思考 (Thoughts on Division of Labor)
Did you ever have the feeling that adding people doesn't help in software development? Did you ever ...
随机推荐
- (Java)面向对象的三大特征
封装.继承与多态 封装 封装的作用(好处) 提高程序安全性,保护数据 隐藏代码的实现细节 统一接口 增加系统可维护性 属性私有(关键字private) 加上Private可使该属性私有于一个类,在其他 ...
- .NET Reflector软件破解
转自:https://blog.csdn.net/zxy13826134783/article/details/89057871 软件和注册机下载地址: 链接:https://pan.baidu.co ...
- Powerful Number 学习笔记
定义 对于一个正整数 \(n\) ,若完全分解之后不存在指数 \(=1\) ,则称 \(n\) 为 \(\text{Powerful Number}\) . 可以发现的是,在 \([1,n]\) 中, ...
- XiaoXin 13Pro-Hackintosh 小新13pro崇尚极简的黑苹果双系统
Lenovo XiaoXin-13-Pro-Hackintosh 关键词:Hackintosh XiaoXin EFI Tutorial Lenovo 以下提及的EFI及其他部分文件见github仓库 ...
- UI BLOCK自定义枚举控件的宽度
三步: 1.修改PresentationStyle属性为Radio Box 2.修改NumberOfColumns属性为指定的宽度(显示字符的个数) 3.将PresentationStyle属性改回O ...
- Visual Studio CMake 项目和 WSL
Visual Studio CMake 项目和 WSL https://devblogs.microsoft.com/cppblog/c-with-visual-studio-2019-and-win ...
- QG-2019-AAAI-Improving Neural Question Generation using Answer Separation
Improving Neural Question Generation using Answer Separation 本篇是2019年发表在AAAI上的一篇文章.该文章在基础的seq2seq模型的 ...
- zip和flatMap没有生效
在Reactor 中flatMap和zip等没有生效 1.一个简单的示例代码如下: 2.示例运行结果 3.得到结论 最近在项目中使用了 Project Reactor ,但发现代码在写着写着有些地方没 ...
- Go语言核心36讲(Go语言进阶技术八)--学习笔记
14 | 接口类型的合理运用 前导内容:正确使用接口的基础知识 在 Go 语言的语境中,当我们在谈论"接口"的时候,一定指的是接口类型.因为接口类型与其他数据类型不同,它是没法被实 ...
- 色彩滤镜矩阵(Color Filter Array)
数码相机上的每个象素都带有一个光感应器,用以测量光线的明亮程度.由于光电二极管是只支持单颜色的装置,它不能区别不同波长的光线.因此,数码相机工程师在相机感应器的上部装上了一套镶嵌式的颜色滤镜,一个颜色 ...