由于是排列,即任意两个数字都各不相同,因此字典序最大的$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. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 200005
  4. 4 #define L (k<<1)
  5. 5 #define R (L+1)
  6. 6 #define mid (l+r>>1)
  7. 7 int n,k,a[N],pos[N],dp[N],nex[N],b[N],f[N<<2];
  8. 8 void update1(int k,int l,int r,int x,int y){
  9. 9 if (l==r){
  10. 10 f[k]=y;
  11. 11 return;
  12. 12 }
  13. 13 if (x<=mid)update1(L,l,mid,x,y);
  14. 14 else update1(R,mid+1,r,x,y);
  15. 15 f[k]=max(f[L],f[R]);
  16. 16 }
  17. 17 int query1(int k,int l,int r,int x,int y){
  18. 18 if ((l>y)||(x>r))return -0x3f3f3f3f;
  19. 19 if ((x<=l)&&(r<=y))return f[k];
  20. 20 return max(query1(L,l,mid,x,y),query1(R,mid+1,r,x,y));
  21. 21 }
  22. 22 void update2(int k,int l,int r,int x){
  23. 23 f[k]++;
  24. 24 if (l==r)return;
  25. 25 if (x<=mid)update2(L,l,mid,x);
  26. 26 else update2(R,mid+1,r,x);
  27. 27 }
  28. 28 int query2(int k,int l,int r,int x){
  29. 29 if (l==r)return l;
  30. 30 if (x<=f[R])return query2(R,mid+1,r,x);
  31. 31 return query2(L,l,mid,x-f[R]);
  32. 32 }
  33. 33 int main(){
  34. 34 scanf("%d%d",&n,&k);
  35. 35 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
  36. 36 for(int i=1;i<=n;i++)pos[a[i]]=i;
  37. 37 if (a[1]<=k){
  38. 38 for(int i=k;i;i--){
  39. 39 printf("%d ",i);
  40. 40 for(int j=pos[i]+1;(j<=n)&&(a[j]>k);j++)printf("%d ",a[j]);
  41. 41 }
  42. 42 return 0;
  43. 43 }
  44. 44 memset(f,-0x3f,sizeof(f));
  45. 45 for(int i=1;i<=n;i++){
  46. 46 dp[i]=query1(1,1,n,a[i]+1,n)+1;
  47. 47 if (a[i]<=a[1])dp[i]=max(dp[i],1);
  48. 48 update1(1,1,n,a[i],dp[i]);
  49. 49 }
  50. 50 for(int i=1;i<=n;i++)
  51. 51 if (dp[i]>=k){
  52. 52 for(int j=1;j<=n;j++)printf("%d ",a[j]);
  53. 53 return 0;
  54. 54 }
  55. 55 memset(f,0,sizeof(f));
  56. 56 for(int i=1;i<=n;i++){
  57. 57 nex[pos[i]]=query2(1,1,n,k-dp[pos[i]]);
  58. 58 if (nex[pos[i]]<pos[i])nex[pos[i]]=0;
  59. 59 update2(1,1,n,pos[i]);
  60. 60 }
  61. 61 for(int i=1;i<=n;i++)nex[0]=max(nex[0],nex[i]);
  62. 62 for(int i=1;i<=n;i++)
  63. 63 if (nex[i]==nex[0])dp[0]=max(dp[0],dp[i]);
  64. 64 for(int i=1;i<nex[0];i++)printf("%d ",a[i]);
  65. 65 for(int i=nex[0];i<=n;i++)b[i-nex[0]]=a[i];
  66. 66 sort(b,b+n-nex[0]+1);
  67. 67 for(int i=k-dp[0]-1;i>=0;i--){
  68. 68 printf("%d ",b[i]);
  69. 69 for(int j=pos[b[i]]+1;(j<=n)&&(a[j]>b[k-dp[0]-1]);j++)printf("%d ",a[j]);
  70. 70 }
  71. 71 }

[atARC114F]Permutation Division的更多相关文章

  1. python from __future__ import division

    1.在python2 中导入未来的支持的语言特征中division(精确除法),即from __future__ import division ,当我们在程序中没有导入该特征时,"/&qu ...

  2. Permutation Sequence

    The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...

  3. [LeetCode] Evaluate Division 求除法表达式的值

    Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...

  4. [LeetCode] Palindrome Permutation II 回文全排列之二

    Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...

  5. [LeetCode] Palindrome Permutation 回文全排列

    Given a string, determine if a permutation of the string could form a palindrome. For example," ...

  6. [LeetCode] Permutation Sequence 序列排序

    The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...

  7. [LeetCode] Next Permutation 下一个排列

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  8. 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 ...

  9. 关于分工的思考 (Thoughts on Division of Labor)

    Did you ever have the feeling that adding people doesn't help in software development? Did you ever ...

随机推荐

  1. 教你 4 步搭建弹性可扩展的 WebAPI

    作者 | 萧起  阿里云云原生团队 本文整理自<Serverless 技术公开课>,关注"Serverless"公众号,回复"入门",即可获取 Se ...

  2. dubbo服务架构介绍

    Provider: 暴露服务的服务提供方. Consumer: 调用远程服务的服务消费方. Registry: 服务注册与发现的注册中心. Monitor: 统计服务的调用次数和调用时间的监控中心. ...

  3. SudokuSolver 1.0:用C++实现的数独解题程序 【一】

    SudokuSolver 1.0 用法与实现效果 SudokuSolver 是一个提供命令交互的命令行程序,提供的命令清单有: H:\Read\num\Release>sudoku.exe Or ...

  4. 解决更新页面版本后用户需CTRL+F5强刷才能应用最新页面

    设置文件永远不从缓存读取 第一步:在html文件设置文件不缓存 <!DOCTYPE html> <html lang="en" class="theme ...

  5. noj加1乘2平方

    广度优先搜索典例 00 题目 描述: 最简单的队列的使用#include <iostream>#include <queue>using namespace std;queue ...

  6. 痞子衡嵌入式:超级下载算法RT-UFL v1.0在Keil MDK下的使用

    痞子衡主导的"学术"项目 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计> v1.0 版发布近 4 个月了,部分客户已经在实际项目开发调试中用上了这个 ...

  7. 论文解读丨表格识别模型TableMaster

    摘要:在此解决方案中把表格识别分成了四个部分:表格结构序列识别.文字检测.文字识别.单元格和文字框对齐.其中表格结构序列识别用到的模型是基于Master修改的,文字检测模型用到的是PSENet,文字识 ...

  8. 谈谈BEM规范(含代码)

    css规范之BEM规范 前言 引用一句经典名言在编程的世界里其中一件最难的事情就是命名,不管是设计到编程语言还是标记语言都会有命名的需求.今天聊的就是关于css的命名规范的发展过程以及演变. 命名的发 ...

  9. the Agiles Scrum Meeting 6

    会议时间:2020.4.14 20:00 1.每个人的工作 今天已完成的工作 增量组:开发广播正文展开收起功能 issues:增量组:广播正文展开收起功能实现 完善组:修复冲刺部分的bug issue ...

  10. python的random模块生成随机数

    python的random函数 random.random() 生成0-1之间的随机数 random.uniform(a,b)生成a,b之间的浮点数 random.randint(a,b)生成a,b之 ...