Atcoder Grand Contest 001 F - Wide Swap(拓扑排序)
咦?鸽子 tzc 来补题解了?奇迹奇迹(
首先考虑什么样的排列可以得到。我们考虑 \(p\) 的逆排列 \(q\),那么每次操作的过程从逆排列的角度思考,就可视作每次在逆排列中交换两个相邻,且元素值之差 \(\ge k\) 的元素。注意到对于两个元素 \(x,y\),如果 \(|x-y|<k\),那么我们肯定永远无法交换它们,它们的相对位置顺序也永远无法改变,因为要改变它们的相对顺序必须交换它们。而一对 \(|q_i-q_j|<k,i<j\) 的 \((i,j)\) 恰好对应一对 \(p_i<p_j,|i-j|<k\) 的 \((i,j)\)。因此对于相距 \(<k\) 的位置,它们的相对大小顺序不能发生变化。而我们能够证明,如果两个排列 \(p,p'\),满足它们相距 \(<k\) 的位置上的元素相对位置大小不变,那么它们之间就能够互相转化,证明我也不太会,一个感性地想法是,我们记排列 \(q\) 满足 \(p\circ q=p'\),那么我们每次总能交换两个数,使得 \(q\) 逆序对大小减一,因此它们能够互相转化。
我们考虑对于 \(|i-j|<k\),如果 \(p_i<p_j\) 则连一条 \(i\to j\) 的边,否则连一条 \(j\to i\) 的边,那么不考虑复杂度的问题,我们的目标就是给每个点赋上一个标号 \(r_i\),使得对于所有有向边 \(u\to v\),都有 \(r_u<r_v\),并且 \(r\) 的字典序尽可能小。这是一个经典问题,考虑这样的过程,我们建反图然后拓扑排序,每次取出编号最大的点然后在上面填 \(n,n-1,\cdots\) 以此类推,类似的题有这个(它是道 Ag 的题但代码异常短)。但是暴力建图复杂度是 \(nk\) 的,无法通过。不过注意到此题建图方式很特殊,\(n^2\) 建边+特殊建图方式 \(=n\log n\)(暴论),注意到一个点 \(x\) 度为 \(0\),当且仅当 \(p_x\) 为 \([x-k+1,x+k-1]\) 的最大值,因此我们考虑用线段树维护这个过程,先一遍扫过去将所有度为 \(0\) 的点压入优先队列,然后每次取出一个点 \(x\) 时,就将 \(p_x\) 改为 \(-\infty\),然后松弛与其相连的点即可。不难发现每次松弛只有 \([x-k+1,x-1]\) 中最大值的位置和 \([x+1,x+k-1]\) 最大值的位置是有用的,只用松弛这两个点即可。
时间复杂度 \(n\log n\)。
const int MAXN=5e5;
int n,m,p[MAXN+5],res[MAXN+5];
struct node{int l,r;pii mx;} s[MAXN*4+5];
void pushup(int k){s[k].mx=max(s[k<<1].mx,s[k<<1|1].mx);}
void build(int k,int l,int r){
s[k].l=l;s[k].r=r;if(l==r) return s[k].mx=mp(p[l],l),void();
int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
pushup(k);
}
void modify(int k,int p,pii v){
if(s[k].l==s[k].r) return s[k].mx=v,void();
int mid=s[k].l+s[k].r>>1;
(p<=mid)?modify(k<<1,p,v):modify(k<<1|1,p,v);
pushup(k);
}
pii query(int k,int l,int r){
if(l<=s[k].l&&s[k].r<=r) return s[k].mx;
int mid=s[k].l+s[k].r>>1;
if(r<=mid) return query(k<<1,l,r);
else if(l>mid) return query(k<<1|1,l,r);
else return max(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
}
priority_queue<int> q;
bool inq[MAXN+5];
void check(int x){
if(!x||inq[x]) return;
if(x==query(1,max(x-m,1),min(x+m,n)).se)
q.push(x),inq[x]=1;
}
int main(){
scanf("%d%d",&n,&m);--m;
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
build(1,1,n);int c=n;
for(int i=1;i<=n;i++) check(i);
while(!q.empty()){
int x=q.top();q.pop();res[x]=c--;
// printf("%d\n",x);
modify(1,x,mp(-INF,0));
check(query(1,max(x-m,1),x).se);
check(query(1,x,min(x+m,n)).se);
} for(int i=1;i<=n;i++) printf("%d\n",res[i]);
return 0;
}
Atcoder Grand Contest 001 F - Wide Swap(拓扑排序)的更多相关文章
- 【AtCoder Grand Contest 001F】Wide Swap [线段树][拓扑]
Wide Swap Time Limit: 50 Sec Memory Limit: 512 MB Description Input Output Sample Input 8 3 4 5 7 8 ...
- JZOJ5405 & AtCoder Grand Contest 001 F. Permutation
题目大意 给出一个长度为\(n\)的排列\(P\)与一个正整数\(k\). 你需要进行如下操作任意次, 使得排列\(P\)的字典序尽量小. 对于两个满足\(|i-j|>=k\) 且\(|P_i- ...
- AtCoder Grand Contest 001 D - Arrays and Palindrome
题目传送门:https://agc001.contest.atcoder.jp/tasks/agc001_d 题目大意: 现要求你构造两个序列\(a,b\),满足: \(a\)序列中数字总和为\(N\ ...
- AtCoder Grand Contest 003 F - Fraction of Fractal
题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_f 题目大意: 给定一个\(H×W\)的黑白网格,保证黑格四连通且至少有一个黑格 定义分形如下 ...
- AtCoder Grand Contest 001 C Shorten Diameter 树的直径知识
链接:http://agc001.contest.atcoder.jp/tasks/agc001_c 题解(官方): We use the following well-known fact abou ...
- [Atcoder Grand Contest 001] Tutorial
Link: AGC001 传送门 A: …… #include <bits/stdc++.h> using namespace std; ; ]; int main() { scanf(& ...
- AtCoder Grand Contest 002 F:Leftmost Ball
题目传送门:https://agc002.contest.atcoder.jp/tasks/agc002_f 题目翻译 你有\(n*k\)个球,这些球一共有\(n\)种颜色,每种颜色有\(k\)个,然 ...
- AtCoder Grand Contest 017 F - Zigzag
题目传送门:https://agc017.contest.atcoder.jp/tasks/agc017_f 题目大意: 找出\(m\)个长度为\(n\)的二进制数,定义两个二进制数的大小关系如下:若 ...
- AtCoder Grand Contest 011 F - Train Service Planning
题目传送门:https://agc011.contest.atcoder.jp/tasks/agc011_f 题目大意: 现有一条铁路,铁路分为\(1\sim n\)个区间和\(0\sim n\)个站 ...
随机推荐
- Github 29K Star的开源对象存储方案——Minio入门宝典
对象存储不是什么新技术了,但是从来都没有被替代掉.为什么?在这个大数据发展迅速地时代,数据已经不单单是简单的文本数据了,每天有大量的图片,视频数据产生,在短视频火爆的今天,这个数量还在增加.有数据表明 ...
- 架构师之路-https底层原理
引子 先说说我对架构师的理解.从业务能力上,需要的是发现问题和解决问题的能力:从团队建设上,需要的是能培养团队的业务能力:从项目管理上,把控好整个项目和软件产品的全生命周期. 我搜索了一下架构师的培训 ...
- [火星补锅] 水题大战Vol.2 T2 && luogu P3623 [APIO2008]免费道路 题解
前言: 如果我自己写的话,或许能想出来正解,但是多半会因为整不出正确性而弃掉. 解析: 这题算是对Kruskal的熟练运用吧. 要求一颗生成树.也就是说,最后的边数是确定的. 首先我们容易想到一个策略 ...
- 单片机STM32在开发中常用库函数详解
1.GPIO初始化函数 用法: voidGPIO_Configuration(void) { GPIO_InitTypeDefGPIO_InitStructure;//GPIO状态恢复默认参数 GPI ...
- 从0到1使用Kubernetes系列(四):搭建第一个应用程序
传统Kubernetes应用搭建 创建Namespace 在一个Kubernetes集群中可以创建多个Namespace进行"环境隔离",当项目和人员众多的时候,可以考虑根据项目的 ...
- tar 解压分割压缩文件
被分割后的压缩文件必须先合并成一个压缩文件才能正常的解压. 第一步.合并压缩文件 第二步.正常解压 $ls TINA-1.3.tar.gzaa TINA-1.3.tar.gzab TINA-1.3.t ...
- Android编译执行envsetup.sh,产生工具命令m、mm、mmm、mmma、tapas 、croot、cgrep、jgrep、 resgrep、godir
一般来说编译一个sdk或者一个比较大的工程项目,第一步都是执行 envsetup.sh这个脚本,比如编译android,qt源码以及其他一些嵌入式的sdk. 而且执行的时候需要特别注意使用 sourc ...
- Swift-技巧(四)设置照片尺寸和格式
摘要 平时实现拍照功能时,都是网上一通搜索,整体复制粘贴,自称无脑实现.但是当要求照片是不同的尺寸和格式( JPEG)时,就费力搞照片.其实在设置拍照时,就可以直接设置照片的尺寸和格式,用直接的方法来 ...
- MySQL到底能否解决幻读问题
先说结论,MySQL 存储引擎 InnoDB 在可重复读(RR)隔离级别下是解决了幻读问题的. 方法:是通过next-key lock在当前读事务开启时,1.给涉及到的行加写锁(行锁)防止写操作:2. ...
- svn与git区别
代码扫描工具介绍:https://baijiahao.baidu.com/s?id=1629218655164599200&wfr=spider&for=pc Git和SVN的区别与联 ...