【递归】【线段树】【堆】AtCoder Regular Contest 080 E - Young Maids
给你一个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;
}
【递归】【线段树】【堆】AtCoder Regular Contest 080 E - Young Maids的更多相关文章
- 【AtCoder Regular Contest 080E】Young Maids [堆][线段树]
Young Maids Time Limit: 50 Sec Memory Limit: 512 MB Description 给定一个排列,每次选出相邻的两个放在队头,要求字典序最小. Input ...
- AtCoder Regular Contest 080 (ARC080) E - Young Maids 线段树 堆
原文链接http://www.cnblogs.com/zhouzhendong/p/8934377.html 题目传送门 - ARC080 E - Young Maids 题意 给定一个长度为$n$的 ...
- AtCoder Regular Contest 080 E - Young Maids
地址:http://arc080.contest.atcoder.jp/tasks/arc080_c 题目: E - Young Maids Time limit : 2sec / Memory li ...
- AtCoder Regular Contest 080
手贱去开了abc,这么无聊.直接arc啊 C - 4-adjacent Time limit : 2sec / Memory limit : 256MB Score : 400 points Prob ...
- AtCoder Regular Contest 080 E:Young Maids
题目传送门:https://arc080.contest.atcoder.jp/tasks/arc080_c 题目翻译 给你一个\(n\)的排列\(p\),一个空序列\(q\),你每次可以从\(p\) ...
- AtCoder Regular Contest 080 D - Grid Coloring
地址:http://arc080.contest.atcoder.jp/tasks/arc080_b 题目: D - Grid Coloring Time limit : 2sec / Memory ...
- AtCoder Regular Contest 080 C - 4-adjacent
地址:http://arc080.contest.atcoder.jp/tasks/arc080_a 题目: C - 4-adjacent Time limit : 2sec / Memory lim ...
- AtCoder Regular Contest 080 [CDEF]
C - 4-adjacent Time limit : 2sec / Memory limit : 256MB Problem Statement We have a sequence of leng ...
- 【Atcoder】ARC 080 E - Young Maids
[算法]数学+堆 [题意]给定n个数的排列,每次操作可以取两个数按序排在新序列的头部,求最小字典序. [题解] 转化为每次找字典序最小的两个数按序排在尾部,则p1和p2的每次选择都必须满足:p1在当前 ...
随机推荐
- css纯样式导航
<style>.dropdown { position: relative; display: inline-block;} .dropdown-content { di ...
- Linux中source命令的用法
source命令: source命令也称为“点命令”,也就是一个点符号(.).source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录.因为linux所有的操作都会变成文 ...
- perl模拟登录(1)
use WWW::Mechanize; my $ua = WWW::Mechanize->new(); $ua->post('http://localhost/dvwa/DVWA-mast ...
- 第一章:读取文件一行IO::File
#!c:\\perl\\bin\\perl.exe use IO::File; #读取一行 my $fd = IO::File->new('perl.txt'); my $one_line = ...
- nmap导出处理脚本
import sys log = open("result.gnmap","r") xls = open("output.csv",&quo ...
- python基础===单元测试unittest
''' 编写一个名为Employee 的类,其方法__init__()接受名.姓和年薪,并 将它们都存储在属性中.编写一个名为give_raise()的方法,它默认将年薪增加5000 美元,但也能够接 ...
- 【常见的SQL Server连接失败错误以及解决方法】
[常见的SQL Server连接失败错误以及解决方法] http://blog.csdn.net/feixianxxx/article/details/5523922 ADO连接SQL Server ...
- vue-cli脚手架引入element UI的正确打开方式
element UI官网教程:http://element-cn.eleme.io/#/zh-CN/component/quickstart 1.完整引入,直接了当,但是组件文件不是按需加载,造成多余 ...
- MVC - 12.HtmlHelper
1.动态生成URL @Url.Action("Index3","Stu3") @Url.RouteUrl("Default2", new { ...
- centos7 安装rlwrap
https://blog.csdn.net/zhjmozhi/article/details/78347216