AtCoder Regular Contest 080 (ARC080) E - Young Maids 线段树 堆
原文链接http://www.cnblogs.com/zhouzhendong/p/8934377.html
题目传送门 - ARC080 E - Young Maids
题意
给定一个长度为$n$的序列$p$,$p$为$1\cdots n$的一个排列。
现在让你每次取出序列$p$的相邻两个,然后把他们按照原来的顺序放进序列$q$的最前面。注意每次这样的操作之后,$p$序列的剩余两半都会合并起来。
不断进行上述操作,直到$p$为空。
最小化序列$q$的字典序,并输出序列$q$。
$n\leq 2\times 10^5$
题解
这题就是随便贪心几下嘛。
定义下标为奇数的项叫做奇项,下标为偶数的项叫做偶数项。
我们考虑倒着还原原序列。
这样可以便于我们取最小字典序。
首先,考虑我们最后一次选择的项的下标在原序列中为$i,j$,那么在这之前,区间$[1,i),(i,j),(j,n]$不可能有相邻项。
于是在最后一次操作之前,这三个区间之间不可能发生跨区间的操作,那么这三个区间的大小显然都是偶数。
那么,我们考虑如何最小化开头两个数。
显然,我们先在全局找一个值最小的奇项$i$,然后在$(i,n]$中找一个值最小的偶项$j$。
然后成功把全局划分成$3$个区间。这个时候如果你去递归,说明你可能没睡好。
我是测完样例才发现错了
显然,虽然没有跨区间的操作,但是这些区间之间的操作是可以交替进行的。
于是我们每次都要找最小的。然后每次都会继续划分子序列,这样会使候选序列中多出一些来。
于是我们需要一个堆来维护最小值。
至于求奇偶项的最小值,只需要在开始的时候写个线段树就可以了。
然后我再一次的把$set$当堆用了。
代码
- #include <bits/stdc++.h>
- using namespace std;
- const int N=200005;
- int n,a[N],t[2][N<<2];
- void update(int o,int rt,int L,int R,int pos){
- if (a[pos]<a[t[o][rt]])
- t[o][rt]=pos;
- if (L==R)
- return;
- int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
- if (pos<=mid)
- update(o,ls,L,mid,pos);
- else
- update(o,rs,mid+1,R,pos);
- }
- int query(int o,int rt,int L,int R,int xL,int xR){
- if (L>xR||R<xL)
- return 0;
- if (xL<=L&&R<=xR)
- return t[o][rt];
- int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
- int Lans=query(o,ls,L,mid,xL,xR);
- int Rans=query(o,rs,mid+1,R,xL,xR);
- return a[Lans]<a[Rans]?Lans:Rans;
- }
- struct seg{
- int L,R,v;
- seg(){}
- seg(int _L,int _R){
- L=_L,R=_R,v=L>R?0:query(L&1,1,1,n,L,R);
- }
- friend bool operator < (seg A,seg B){
- return a[A.v]<a[B.v];
- }
- };
- int scnt=0;
- set <seg> S;
- int main(){
- scanf("%d",&n);
- a[0]=n+1;
- for (int i=1;i<=n;i++){
- scanf("%d",&a[i]);
- update(i&1,1,1,n,i);
- }
- S.clear();
- S.insert(seg(1,n));
- for (int i=1;i<=n/2;i++){
- seg now=*S.begin();
- S.erase(S.begin());
- int L=now.L,R=now.R;
- int Lmid=now.v,Rmid=query((Lmid&1)^1,1,1,n,Lmid,R);
- printf("%d %d ",a[Lmid],a[Rmid]);
- S.insert(seg(L,Lmid-1));
- S.insert(seg(Lmid+1,Rmid-1));
- S.insert(seg(Rmid+1,R));
- }
- return 0;
- }
AtCoder Regular Contest 080 (ARC080) E - Young Maids 线段树 堆的更多相关文章
- 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 E:Young Maids
题目传送门:https://arc080.contest.atcoder.jp/tasks/arc080_c 题目翻译 给你一个\(n\)的排列\(p\),一个空序列\(q\),你每次可以从\(p\) ...
- AtCoder Regular Contest 080 [CDEF]
C - 4-adjacent Time limit : 2sec / Memory limit : 256MB Problem Statement We have a sequence of leng ...
- 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
给你一个1~n的排列p,n是偶数,每次从中任选一对相邻的数出来,插到排列q的开头,如此循环,问你所能得到的字典序最小的排列q. 我们先确定q开头的两个数q1,q2,q1一定是p的奇数位的最小的数,而q ...
- 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 arc080E Young Maids(线段树+优先队列)
给出一个n排列,每次可以选择相邻的两个数字放在新的排列首部,问最后形成的新的排列字典序最小是? 考虑新排列的第一个数字,则应是下标为奇数的最小数,下标不妨设为i.第二个数字应该下标大于i且为偶数的最小 ...
- AtCoder Regular Contest 061
AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...
随机推荐
- ASP.NET MVC5高级编程 之 数据注解和验证
客户端验证逻辑会对用户向表单输入的数据给出一个即时反馈.而之所以需要服务器端验证,是因为来自网络的信息都是不能被信任的. 当在ASP.NET MVC设计模式上下文中谈论验证时,主要关注的是验证模型的值 ...
- postman 设置api_token,测试数据等操作
在postman的环境变量中先设置好一个用户的token(事先你的数据库里面要有用户的这个数据),如下图: 然后在api请求的url 的head头部添加对应的token键名,value值用花括号{{t ...
- scrapy 在迭代爬取时被拒 offsite 增加dont_filter=True
- AndroidManifest.xml 最全详解
AndroidManifest.xml 是每个android程序中必须的文件,它位于整个项目的根目录.我们每天都在使用这个文件,往里面配置程序运行所必要的组件,权限,以及一些相关信息.但是对于这个文件 ...
- AES加解密程序的实现
AES加解密程序的实现正常情况,用户不能访问sys.dbms_crypto,需要DBA授权:grant execute on dbms_crypto to crm;建立加解密的PKG_AES包:CRE ...
- swift 实践- 12 -- UIPickerView
import UIKit class ViewController: UIViewController , UIPickerViewDelegate,UIPickerViewDataSource{ v ...
- ORACLE in与exists语句的区别
select * from A where id in(select id from B) 以上查询使用了in语句,in()只执行一次,它查出B表中的所有id字段并缓存起来.之后,检查A表的id是否与 ...
- Confluence 6 指定日志选项和已知问题
指定 Confluence 日志选项 这里是一些特定的日志配置,你可能在对问题进行调试的时候需要. 在日志中记录数据库使用的 SQL 查询请求 你可能希望增加日志的中的内容,记录 Confluence ...
- http超文本协议
当今web程序的开发技术真是百家争鸣,ASP.NET, PHP, JSP,Perl, AJAX 等等. 无论Web技术在未来如何发展,理解Web程序之间通信的基本协议相当重要, 因为它让我们理解了We ...
- 第七篇 python基础之函数,递归,内置函数
一 数学定义的函数与python中的函数 初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因 ...