JZOJ 5405. 【NOIP2017提高A组模拟10.10】Permutation
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相关推荐
- 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 ...
- JZOJ 5372. 【NOIP2017提高A组模拟9.17】猫
Description 信息组最近猫成灾了!隔壁物理组也拿猫没办法.信息组组长只好去请神刀手来帮他们消灭猫.信息组现在共有n 只猫(n 为正整数),编号为1 到n,站成了一个环,第i 只猫的左边是第i ...
- JZOJ 5400. 【NOIP2017提高A组模拟10.7】Repulsed
Description 小w 心里的火焰就要被熄灭了. 简便起见,假设小w 的内心是一棵n -1 条边,n 个节点的树. 现在你要在每个节点里放一些个灭火器,每个节点可以放任意多个. 接下来每个节点都 ...
- JZOJ 100026. 【NOIP2017提高A组模拟7.7】图
Description 有一个n个点n条边的有向图,每条边为< i,f(i),w(i)>,意思是i指向f(i)的边权为w(i)的边,现在小A想知道,对于每个点的si和mi. si:由i出发 ...
- JZOJ 5379. 【NOIP2017提高A组模拟9.21】Victor爱数字
Description Victor 是一名热爱数字的同学.他最近在思考这样一个问题: 一个字符串是回文的当且仅当它倒过来还和原来相同.那么如果一个数的数串没有一个长度超过1 的子串是回文串的话,它就 ...
- 【JZOJ 5405】【NOIP2017提高A组模拟10.10】Permutation
Description 你有一个长度为n 的排列P 与一个正整数K 你可以进行如下操作若干次使得排列的字典序尽量小 对于两个满足|i-j|>=K 且|Pi-Pj| = 1 的下标i 与j,交换P ...
- JZOJ 5404. 【NOIP2017提高A组模拟10.10】Graph
Description 给定一张n个点m条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通 你想在这张图上进行若干次旅游,每次旅游可以任选一个点x作为起点,再走到一个与x 直接有边相连的点y ...
- 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 ...
- JZOJ 5398. 【NOIP2017提高A组模拟10.7】Adore
Description 小w 偶然间见到了一个DAG. 这个DAG 有m 层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有k 个节点. 现在小w 每次可以取反第i(1 < i &l ...
最新文章
- HTTP Response中的Chunked编码
- node.js入门系列(一)--Node.js简介
- Google Chrome Native Messaging开发实录(一)背景介绍
- 泽泽计算机科技,《计算机与信息技术》大学技能学习丛书.pdf
- React开发(207):react代码分割之context的动态
- cas server php下载,关于用CAS Server与Php、Jetty配置实现SSO#4
- PHP的rm指令,git rm 命令
- MySQL复习值代码知识点(1)
- 沥青防水卷材行业调研报告 - 市场现状分析与发展前景预测
- 几款KINECT应用
- Python游戏编程(一)“猜数字”游戏
- python snap7 plc db_python 用Snap7读写西门子PLC中DB块
- python中timeout什么意思_Python爬虫(五)timeout以及retrying的使用
- 6款免费网络延迟测试工具
- hdu 2036 改革春风吹满地(叉积求多边形面积)
- JS如何获取屏幕、浏览器及网页高度宽度?
- python人机猜拳_python实现人机猜拳小游戏
- add_metrology_object_circle_measure (对齐测量模型)
- 人工智能细分领域受关注|人工智能|领域|智能
- Linux下安装google浏览器
热门文章
- keil5建立多文件的时候为什么总是出错
- matlab中基本函数的用法
- android 实训的背景,Android实训项目作业.doc
- caffe源码分析:layer.hpp分析
- [云炬创业基础笔记]做好市场调研
- PHP中的else怎么用,php中ifelse与elseif使用区别实例介绍
- opencl获取gpu信息_如果在尝试获取OpenCL gpu设备类型时,Char *语句出现问题
- linux退出 putty_使用putty远程连接linux防止关闭putty程序就停止
- 稠密峰值聚类 - Science2014
- 细说HTML元素的ID和Name属性的区别