一道挺有意思的题目,在这里记录一下。

题目大意

给你一个长度为 \(n\) 的排列,每一次你可以取出相邻的两个数将其放在答案序列的开头,最后问你字典序最小的答案序列是什么。

题解

由于最后是求字典序最小,所以我们肯定需要倒序求解,所以我们需要考虑如何取才能使得剩下的序列合法。

如果我们在区间 \([L,R]\) 当前选择点 \(l\) 和点 \(r\) ,那么最后的区间很显然会被我们分成三部分, \([L,l-1]\) , \([l+1,r-1]\) 和 \([r+1,R]\) 。而且这三个区间的长度必须为偶数才可以满足区间同时也可分。我们就可以用一个优先队列来模拟一下,每一次取出当前所以区间中可以选择字典最小的点对的区间,再将其拆分为三个区间。不断重复此操作直到最后所有的数都被取出即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,a[N],b[N];
struct Point{int data,loc;};
bool operator < (const Point a,const Point b){return a.data<b.data;}
struct Seg_Tree
{
struct Node{Point data;}tr[N<<2];
void up(int u){tr[u].data=min(tr[u<<1].data,tr[u<<1|1].data);}
void build(int u,int l,int r,int a[])
{
if(l==r)
{
tr[u].data.data=a[l];
tr[u].data.loc=l;
return ;
}
int mid=(l+r)>>1;
build(u<<1,l,mid,a);
build(u<<1|1,mid+1,r,a);
up(u);
}
void chg(int u,int l,int r,int x)
{
if(l==r){tr[u].data.data=1e9+7;return ;}
int mid=(l+r)>>1;
if(x<=mid) chg(u<<1,l,mid,x);
else chg(u<<1|1,mid+1,r,x);
up(u);
}
Point query(int u,int l,int r,int x,int y)
{
if(x<=l&&r<=y) return tr[u].data;
int mid=(l+r)>>1;Point res={1000000007,0};
if(x<=mid) res=min(res,query(u<<1,l,mid,x,y));
if(y>mid) res=min(res,query(u<<1|1,mid+1,r,x,y));
return res;
}
}t[2];//0为偶,1为奇
struct Data{int l,r;Point data;};
bool operator < (const Data a,const Data b){return a.data.data>b.data.data;}
priority_queue<Data> q;
vector<int> res;
int main()
{
cin>>n;
for(int i=1,x;i<=n;++i)
{
scanf("%d",&x);
if(i&1) a[i]=1e9+7,b[i]=x;
else a[i]=x,b[i]=1e9+7;
}
t[0].build(1,1,n,a);
t[1].build(1,1,n,b);
Data tmp;
tmp.l=1,tmp.r=n;
tmp.data=t[1].query(1,1,n,1,n);
q.push(tmp);
for(int i=1;i<=n/2;++i)
{
tmp=q.top(),q.pop();
int tag=tmp.l%2;
// printf("%d\n",tag);
Point L=tmp.data,R=t[tag^1].query(1,1,n,L.loc+1,tmp.r);
// printf("%d %d %d %d\n",tmp.l,tmp.r,L.data,R.data);
res.push_back(L.data),res.push_back(R.data);
Data now;
now.l=tmp.l,now.r=L.loc-1;
if(now.l<=now.r)
{
now.data=t[tag].query(1,1,n,now.l,now.r);
q.push(now);
}
now.l=L.loc+1,now.r=R.loc-1;
if(now.l<=now.r)
{
now.data=t[tag^1].query(1,1,n,now.l,now.r);
q.push(now);
}
now.l=R.loc+1,now.r=tmp.r;
if(now.l<=now.r)
{
now.data=t[tag].query(1,1,n,now.l,now.r);
q.push(now);
}
}
for(int i=0;i<(int)res.size();++i) printf("%d ",res[i]);
printf("\n");
return 0;
}

AT2688 [ARC080C] Young Maids的更多相关文章

  1. AtCoder Regular Contest 080 (ARC080) E - Young Maids 线段树 堆

    原文链接http://www.cnblogs.com/zhouzhendong/p/8934377.html 题目传送门 - ARC080 E - Young Maids 题意 给定一个长度为$n$的 ...

  2. 【AtCoder Regular Contest 080E】Young Maids [堆][线段树]

    Young Maids Time Limit: 50 Sec  Memory Limit: 512 MB Description 给定一个排列,每次选出相邻的两个放在队头,要求字典序最小. Input ...

  3. AtCoder Regular Contest 080 E - Young Maids

    地址:http://arc080.contest.atcoder.jp/tasks/arc080_c 题目: E - Young Maids Time limit : 2sec / Memory li ...

  4. Young Maids

    E - Young Maids Time limit : 2sec / Memory limit : 256MB Score : 800 points Problem Statement Let N  ...

  5. Atcoder arc080E Young Maids(线段树+优先队列)

    给出一个n排列,每次可以选择相邻的两个数字放在新的排列首部,问最后形成的新的排列字典序最小是? 考虑新排列的第一个数字,则应是下标为奇数的最小数,下标不妨设为i.第二个数字应该下标大于i且为偶数的最小 ...

  6. 【递归】【线段树】【堆】AtCoder Regular Contest 080 E - Young Maids

    给你一个1~n的排列p,n是偶数,每次从中任选一对相邻的数出来,插到排列q的开头,如此循环,问你所能得到的字典序最小的排列q. 我们先确定q开头的两个数q1,q2,q1一定是p的奇数位的最小的数,而q ...

  7. 【Atcoder】ARC 080 E - Young Maids

    [算法]数学+堆 [题意]给定n个数的排列,每次操作可以取两个数按序排在新序列的头部,求最小字典序. [题解] 转化为每次找字典序最小的两个数按序排在尾部,则p1和p2的每次选择都必须满足:p1在当前 ...

  8. AtCoder Regular Contest 080 E:Young Maids

    题目传送门:https://arc080.contest.atcoder.jp/tasks/arc080_c 题目翻译 给你一个\(n\)的排列\(p\),一个空序列\(q\),你每次可以从\(p\) ...

  9. Atcoder 乱做

    最近感觉自己思维僵化,啥都不会做了-- ARC103 F Distance Sums 题意 给定第 \(i\) 个点到所有点的距离和 \(D_i\) ,要求构造一棵合法的树.满足第 \(i\) 个点到 ...

随机推荐

  1. ostringstream、istringstream、stringstream(转)

    看一下C++风格的串流控制,C++引入了ostringstream.istringstream.stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件. istring ...

  2. shell编程之算术扩展(引号、命令替换、算术扩展)

    1.单引号 .双引号.反引号的区别 单引号:忽略所有特殊字符 双引号:忽略大部分特殊字符($  `等字符除外) [root@tlinux shell]# echo '*' * [root@tlinux ...

  3. 面试题:了解MySQL的Flush-List吗?顺便说一下脏页的落盘机制!(文末送书)

    Hi,大家好!我是白日梦! 今天我要跟你分享的MySQL话题是:"了解Flush-List吗?顺便说一下脏页的落盘机制!(文末送书)" 本文是MySQL专题的第 8 篇,共110篇 ...

  4. Java初始化静态变量的时间顺序

    1. 开始吧! 今天,我们来探讨交流下静态变量初始化过程.Java虚拟机在类加载期间也同样遵循这个过程. 2. 初始化过程 在较高的层次上,JVM执行以下步骤: 首先,加载并链接类.然后,这个过程的& ...

  5. 测试_QTP使用

    1.Qtp是什么? QTP是Quick Test Professional的简称,是一种自动测试工具.使用QTP的目的是想用它来执行重复的自动化测试,主要是用于回归测试和测试同一软件的新版本.(百度百 ...

  6. apache-commons和guava的工具类

    apache-commons工具类:https://www.iteye.com/blog/zhoualine-1770014 guava工具类:https://blog.csdn.net/Dream_ ...

  7. 在CorelDRAW中如何完成属性的复制

    复制功能在任何一个编辑软件中都是必不可少.使用率很高的一个功能,在矢量图形设计软件CorelDRAW 中也不例外.关于对象的复制这里就不过多示意了,主要为大家示范一下如何在设计中复制对象的一些属性. ...

  8. guitar pro系列教程(五):Guitar Pro音轨属性之小节的功能

    又到了guitar pro系列教程新的一章,本章节小编将采用图文相结合的方式与大家一起来讨论下关于Guitar Pro小节的功能,感兴趣的小伙伴都可以进来看看哦,如下图所示: 我们看到小节这选项栏中分 ...

  9. uniapp自定义picker城市多级联动组件

    uniapp自定义picker城市多级联动组件 支持多端--h5.app.微信小程序.支付宝小程序... 支持自定义配置picker插件级数 支持无限级 注意事项:插件传入数据格式为children树 ...

  10. Codeforces Round #677 (Div. 3) E、G题解

    E. Two Round Dances #圆排列 题目链接 题意 \(n\)(保证偶数)个人,要表演一个节目,这个节目包含两种圆形舞蹈,而每种圆形舞蹈恰好需要\(n/2\)个人,每个人只能跳一种圆形舞 ...