给你一个1~n的排列p,n是偶数,每次从中任选一对相邻的数出来,插到排列q的开头,如此循环,问你所能得到的字典序最小的排列q。

我们先确定q开头的两个数q1,q2,q1一定是p的奇数位的最小的数,而q2一定是q1后面最小的偶数位的数,这很显然。

然后记q1,q2在p中的位置分别是L,R,把p分成三段[1,L],[L+1,R-1],[R+1,n],递归处理,当前区间[l,r],每次取的一对的左端点L必然是与当前区间左端点l奇偶性相同的最小的数,而R必然是L右侧与当前区间左端点l奇偶性不同的最小的数。

可以对奇数位和偶数位分别维护一个线段树。

重点是输出答案,我们从前往后构造q,我们发现,所有的数对形成了一个树形结构,比如说[l,r],通过之前我们说的过程,取得数对L,R,则[L,R]之间的数对都必须在L,R输出之后才能输出,我们把这些数对记作[L,R]的子树,递归把树建出来。

然后对我们构造出的这棵树,一开始把所有根的儿子加入堆,我们每次取当前堆里数对左侧的数最小的,输出,然后把它的儿子都加进堆,因为它的所有儿子都“解除了封锁”。如此直到堆空即可。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
priority_queue<int,vector<int>,greater<int> >Heap;
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
int v[200005],first[200005],nex[200005],e;
void AddEdge(int U,int V){
v[++e]=V;
nex[e]=first[U];
first[U]=e;
}
int a[200005],cnt,ma[200005],pai[200005];
int minv[2][100005<<4],n,pos[200005];
void update(int o,int p,int v,int rt,int l,int r)
{
if(l==r)
{
minv[o][rt]+=v;
return;
}
int m=(l+r>>1);
if(p<=m) update(o,p,v,lson);
else update(o,p,v,rson);
minv[o][rt]=min(minv[o][rt<<1],minv[o][rt<<1|1]);
}
int query(int o,int ql,int qr,int rt,int l,int r)
{
if(ql<=l&&r<=qr) return minv[o][rt];
int m=(l+r>>1);
int res=2147483647;
if(ql<=m) res=min(res,query(o,ql,qr,lson));
if(m<qr) res=min(res,query(o,ql,qr,rson));
return res;
}
void work(int l,int r,int f){
if(l>=r){
return;
}
int L=pos[query(l&1,ma[l],(l%2 == r%2) ? ma[r] : ma[r-1],1,1,n/2)];
int R=pos[query((L+1)&1,ma[L+1],((L+1)%2 == r%2) ? ma[r] : ma[r-1],1,1,n/2)];
pai[a[L]]=a[R];
AddEdge(a[f],a[L]);
work(l,L-1,f);
work(L+1,R-1,L);
work(R+1,r,f);
}
int main(){
// freopen("c.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
pos[a[i]]=i;
update(i&1,i/2+(i&1),a[i],1,1,n/2);
ma[i]=i/2+(i&1);
}
if(n==2){
printf("%d %d\n",a[1],a[2]);
return 0;
}
work(1,n,0);
for(int i=first[0];i;i=nex[i]){
Heap.push(v[i]);
}
while(!Heap.empty()){
int U=Heap.top(); Heap.pop();
cnt+=2;
printf("%d %d%c",U,pai[U],cnt==n ? '\n' : ' ');
for(int i=first[U];i;i=nex[i]){
Heap.push(v[i]);
}
}
return 0;
}

最新文章

  1. 《JavaScript设计模式与开发实践》整理
  2. 《高性能javascript》 领悟随笔之-------DOM编程篇(二)
  3. 12,13 Proxy和Reflect
  4. 修改Linux可显示的行数
  5. 利用 cos 组件实现jsp中上传附件
  6. Javascript的匿名函数
  7. Java从入门到精通——数据库篇之OJDBC版本区别
  8. spinner中的onNothingSelected方法到底什么时候调用?
  9. 第一个Xcode项目 - 代码修改布局约束
  10. 电商网站垮IDC数据备份,MySql主从同步,图片及其它数据文件的同步
  11. 1020. Tree Traversals
  12. PyCharm 去掉自动保存功能
  13. createElement的应用
  14. idea导入本地maven项目
  15. docker镜像保存及导出(save,export)
  16. Linux常用基本命令(tail )
  17. vue打包后图片找不到情况
  18. C++如何实现DNS域名解析&lt;转&gt;
  19. Oracle索引相关
  20. swift对比object-c

热门文章

  1. .NET Core Data Access
  2. NYOJ 1237 最大岛屿 (深搜)
  3. bzoj 1968 数学
  4. eCharts_基于eCharts开发的一个多图表页面
  5. Vue组件-组件的属性
  6. python基础===open()文件处理使用介绍
  7. windows7 能连接移动硬盘 无法显示盘符
  8. PXC 避免加入集群时发生SST
  9. 用selenium 模块控制浏览器
  10. git学习笔记三