Description

你有一个长度为n 的排列P 与一个正整数K
你可以进行如下操作若干次使得排列的字典序尽量小
对于两个满足|i-j|>=K 且|Pi-Pj| = 1 的下标i 与j,交换Pi 与Pj

Input

第一行包括两个正整数n 与K
第二行包括n 个正整数,第i 个正整数表示Pi

Output

输出一个新排列表示答案
输出共n 行,第i 行表示Pi

Sample Input

8 3
4 5 7 8 3 1 2 6

Sample Output

1
2
6
7
5
3
4
8

Data Constraint

对于前20% 的数据满足n <= 6
对于前50% 的数据满足n <= 2000
对于100% 的数据满足n <= 500000

Solution

  • 读入 p[i]p[i] ,转化为: q[p[i]]=iq[p[i]]=i ,q[i]q[i] 表示值为 ii 的位置在哪。

  • 考虑对于 q[i]q[i] 和 q[j]q[j] ,若 |q[i]−q[j]|<k\left|q[i]-q[j]\right| (相距小于 kk),则 q[i]q[i] 和 q[j]q[j] 始终不能互换位置。

  • 于是 q[i]q[i] 向 q[j] (i>j)q[j]\ (i>j) 连一条有向边即可,这样就构成了一个有向无环图。

  • 将入度为 0 的点加入一个小根堆,做一遍拓扑排序。

  • 倒着枚举 ii ,每次从堆里取出一个编号最小的 xx,

  • 使 p[i]=xp[i]=x ,再将 xx 连出的点入度减一,为 0 则加入堆中。

  • 最后使 q[p[i]]=iq[p[i]]=i , 再将 qq 输出即可。

  • 为什么要维护一个堆呢?因为如果两点连了边(不能位置互换),就不会同时存在于堆中。

  • 在队中的点,肯定是可以位置互换的,那肯定是将小的数填在位置小那里,才能保证字典序最小。

-但是这种连边时间复杂度达到了 O(N2)O(N^2) ,这样就超时了。

  • 由于一个点只需与离它最近的点连边,维护一个维护最小值的线段树,

  • 倒着枚举 ii ,每次查询 [q[i]−k+1,q[i]][q[i]-k+1,q[i]] 和 [q[i],q[i]+k−1][q[i],q[i]+k-1] 两个区间的最小值

  • 即距离最近的两个点(一大一小),连边后再将 q[i]q[i] 这个位置单点修改成编号 ii 即可。

  • 这样同样做一次拓扑排序,不会影响正确性,时间复杂度就成了 O(N log N)O(N\ log\ N) 。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=5e5+1;
int tot;
int a[N],b[N],f[N<<2];
int first[N],next[N<<2],en[N<<2],d[N];
bool bz[N];
priority_queue<int,vector<int>,less<int> >q;
inline int read()
{int X=0,w=1; char ch=0;while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*w;
}
inline void insert(int x,int y)
{next[++tot]=first[x];first[x]=tot;en[tot]=y;d[y]++;
}
inline void change(int v,int l,int r,int x,int y)
{if(l==r){f[v]=y;return;}int mid=(l+r)>>1;if(x<=mid) change(v<<1,l,mid,x,y); else change(v<<1|1,mid+1,r,x,y);f[v]=min(f[v<<1],f[v<<1|1]);
}
inline int find(int v,int l,int r,int x,int y)
{if(x<=l && r<=y) return f[v];int mid=(l+r)>>1;if(y<=mid) return find(v<<1,l,mid,x,y);if(x>mid) return find(v<<1|1,mid+1,r,x,y);return min(find(v<<1,l,mid,x,mid),find(v<<1|1,mid+1,r,mid+1,y));
}
int main()
{int n=read(),k=read();for(int i=1;i<=n;i++) b[a[i]=read()]=i;memset(f,60,sizeof(f));for(int i=n;i;i--){int x=find(1,1,n,b[i]-k+1,b[i]);if(x<=n) insert(b[x],b[i]);x=find(1,1,n,b[i],b[i]+k-1);if(x<=n) insert(b[x],b[i]);change(1,1,n,b[i],i);}for(int i=1;i<=n;i++)if(!d[i]) q.push(i);for(int i=n;i;i--){a[i]=q.top();q.pop();for(int j=first[a[i]];j;j=next[j])if(!--d[en[j]]) q.push(en[j]);}for(int i=1;i<=n;i++) b[a[i]]=i; for(int i=1;i<=n;i++) printf("%d\n",b[i]);return 0;
}

JZOJ 5405. 【NOIP2017提高A组模拟10.10】Permutation相关推荐

  1. JZOJ 100035. 【NOIP2017提高A组模拟7.10】区间

    Description Input Output Sample Input sample1: 4 2 10 5 1 1 10 sample2: 1000 97 96998351 41 1668 505 ...

  2. JZOJ 5372. 【NOIP2017提高A组模拟9.17】猫

    Description 信息组最近猫成灾了!隔壁物理组也拿猫没办法.信息组组长只好去请神刀手来帮他们消灭猫.信息组现在共有n 只猫(n 为正整数),编号为1 到n,站成了一个环,第i 只猫的左边是第i ...

  3. JZOJ 5400. 【NOIP2017提高A组模拟10.7】Repulsed

    Description 小w 心里的火焰就要被熄灭了. 简便起见,假设小w 的内心是一棵n -1 条边,n 个节点的树. 现在你要在每个节点里放一些个灭火器,每个节点可以放任意多个. 接下来每个节点都 ...

  4. JZOJ 100026. 【NOIP2017提高A组模拟7.7】图

    Description 有一个n个点n条边的有向图,每条边为< i,f(i),w(i)>,意思是i指向f(i)的边权为w(i)的边,现在小A想知道,对于每个点的si和mi. si:由i出发 ...

  5. JZOJ 5379. 【NOIP2017提高A组模拟9.21】Victor爱数字

    Description Victor 是一名热爱数字的同学.他最近在思考这样一个问题: 一个字符串是回文的当且仅当它倒过来还和原来相同.那么如果一个数的数串没有一个长度超过1 的子串是回文串的话,它就 ...

  6. 【JZOJ 5405】【NOIP2017提高A组模拟10.10】Permutation

    Description 你有一个长度为n 的排列P 与一个正整数K 你可以进行如下操作若干次使得排列的字典序尽量小 对于两个满足|i-j|>=K 且|Pi-Pj| = 1 的下标i 与j,交换P ...

  7. JZOJ 5404. 【NOIP2017提高A组模拟10.10】Graph

    Description 给定一张n个点m条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通 你想在这张图上进行若干次旅游,每次旅游可以任选一个点x作为起点,再走到一个与x 直接有边相连的点y ...

  8. JZOJ 5401. 【NOIP2017提高A组模拟10.8】Star Way To Heaven

    Description Input Output Sample Input 10 5 2 1 1 2 3 Sample Output 1.11803399 Data Constraint Soluti ...

  9. JZOJ 5398. 【NOIP2017提高A组模拟10.7】Adore

    Description 小w 偶然间见到了一个DAG. 这个DAG 有m 层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有k 个节点. 现在小w 每次可以取反第i(1 < i &l ...

最新文章

  1. HTTP Response中的Chunked编码
  2. node.js入门系列(一)--Node.js简介
  3. Google Chrome Native Messaging开发实录(一)背景介绍
  4. 泽泽计算机科技,《计算机与信息技术》大学技能学习丛书.pdf
  5. React开发(207):react代码分割之context的动态
  6. cas server php下载,关于用CAS Server与Php、Jetty配置实现SSO#4
  7. PHP的rm指令,git rm 命令
  8. MySQL复习值代码知识点(1)
  9. 沥青防水卷材行业调研报告 - 市场现状分析与发展前景预测
  10. 几款KINECT应用
  11. Python游戏编程(一)“猜数字”游戏
  12. python snap7 plc db_python 用Snap7读写西门子PLC中DB块
  13. python中timeout什么意思_Python爬虫(五)timeout以及retrying的使用
  14. 6款免费网络延迟测试工具
  15. hdu 2036 改革春风吹满地(叉积求多边形面积)
  16. JS如何获取屏幕、浏览器及网页高度宽度?
  17. python人机猜拳_python实现人机猜拳小游戏
  18. add_metrology_object_circle_measure (对齐测量模型)
  19. 人工智能细分领域受关注|人工智能|领域|智能
  20. Linux下安装google浏览器

热门文章

  1. keil5建立多文件的时候为什么总是出错
  2. matlab中基本函数的用法
  3. android 实训的背景,Android实训项目作业.doc
  4. caffe源码分析:layer.hpp分析
  5. [云炬创业基础笔记]做好市场调研
  6. PHP中的else怎么用,php中ifelse与elseif使用区别实例介绍
  7. opencl获取gpu信息_如果在尝试获取OpenCL gpu设备类型时,Char *语句出现问题
  8. linux退出 putty_使用putty远程连接linux防止关闭putty程序就停止
  9. 稠密峰值聚类 - Science2014
  10. 细说HTML元素的ID和Name属性的区别