给你一个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]的子树,递归把树建出来。

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

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<queue>
  5. using namespace std;
  6. priority_queue<int,vector<int>,greater<int> >Heap;
  7. #define lson rt<<1,l,m
  8. #define rson rt<<1|1,m+1,r
  9. int v[200005],first[200005],nex[200005],e;
  10. void AddEdge(int U,int V){
  11. v[++e]=V;
  12. nex[e]=first[U];
  13. first[U]=e;
  14. }
  15. int a[200005],cnt,ma[200005],pai[200005];
  16. int minv[2][100005<<4],n,pos[200005];
  17. void update(int o,int p,int v,int rt,int l,int r)
  18. {
  19. if(l==r)
  20. {
  21. minv[o][rt]+=v;
  22. return;
  23. }
  24. int m=(l+r>>1);
  25. if(p<=m) update(o,p,v,lson);
  26. else update(o,p,v,rson);
  27. minv[o][rt]=min(minv[o][rt<<1],minv[o][rt<<1|1]);
  28. }
  29. int query(int o,int ql,int qr,int rt,int l,int r)
  30. {
  31. if(ql<=l&&r<=qr) return minv[o][rt];
  32. int m=(l+r>>1);
  33. int res=2147483647;
  34. if(ql<=m) res=min(res,query(o,ql,qr,lson));
  35. if(m<qr) res=min(res,query(o,ql,qr,rson));
  36. return res;
  37. }
  38. void work(int l,int r,int f){
  39. if(l>=r){
  40. return;
  41. }
  42. int L=pos[query(l&1,ma[l],(l%2 == r%2) ? ma[r] : ma[r-1],1,1,n/2)];
  43. int R=pos[query((L+1)&1,ma[L+1],((L+1)%2 == r%2) ? ma[r] : ma[r-1],1,1,n/2)];
  44. pai[a[L]]=a[R];
  45. AddEdge(a[f],a[L]);
  46. work(l,L-1,f);
  47. work(L+1,R-1,L);
  48. work(R+1,r,f);
  49. }
  50. int main(){
  51. // freopen("c.in","r",stdin);
  52. scanf("%d",&n);
  53. for(int i=1;i<=n;++i){
  54. scanf("%d",&a[i]);
  55. pos[a[i]]=i;
  56. update(i&1,i/2+(i&1),a[i],1,1,n/2);
  57. ma[i]=i/2+(i&1);
  58. }
  59. if(n==2){
  60. printf("%d %d\n",a[1],a[2]);
  61. return 0;
  62. }
  63. work(1,n,0);
  64. for(int i=first[0];i;i=nex[i]){
  65. Heap.push(v[i]);
  66. }
  67. while(!Heap.empty()){
  68. int U=Heap.top(); Heap.pop();
  69. cnt+=2;
  70. printf("%d %d%c",U,pai[U],cnt==n ? '\n' : ' ');
  71. for(int i=first[U];i;i=nex[i]){
  72. Heap.push(v[i]);
  73. }
  74. }
  75. return 0;
  76. }

【递归】【线段树】【堆】AtCoder Regular Contest 080 E - Young Maids的更多相关文章

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

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

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

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

  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. AtCoder Regular Contest 080

    手贱去开了abc,这么无聊.直接arc啊 C - 4-adjacent Time limit : 2sec / Memory limit : 256MB Score : 400 points Prob ...

  5. AtCoder Regular Contest 080 E:Young Maids

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

  6. AtCoder Regular Contest 080 D - Grid Coloring

    地址:http://arc080.contest.atcoder.jp/tasks/arc080_b 题目: D - Grid Coloring Time limit : 2sec / Memory ...

  7. AtCoder Regular Contest 080 C - 4-adjacent

    地址:http://arc080.contest.atcoder.jp/tasks/arc080_a 题目: C - 4-adjacent Time limit : 2sec / Memory lim ...

  8. AtCoder Regular Contest 080 [CDEF]

    C - 4-adjacent Time limit : 2sec / Memory limit : 256MB Problem Statement We have a sequence of leng ...

  9. 【Atcoder】ARC 080 E - Young Maids

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

随机推荐

  1. peewee外键性能问题

    # 转载自:https://www.cnblogs.com/miaojiyao/articles/5217757.html 下面讨论一下用peewee的些许提高性能的方法. 避免N+1查询 N+1查询 ...

  2. Exploring Qualcomm's TrustZone Implementation

    转自  http://bits-please.blogspot.com/2015/08   (需要FQ, 狗日的墙) In this blog post, we'll be exploring Qua ...

  3. swift中闭包的循环引用

    首先我们先创造一个循环引用 var nameB:(()->())? override func viewDidLoad() { super.viewDidLoad() let bu = UIBu ...

  4. DevExpress.XtraTreeList 小结

    搞了半天才绑定好,没有弄清楚父子之间的关系 <dx:ASPxTreeList ID="ASPxTreeList1" runat="server" Auto ...

  5. springmvc中输出字符串

    /** * 输出文字 * @param response * @param s */ public static void responseOut(HttpServletResponse respon ...

  6. mycncart 前台代码跟踪

    1.进入根目录的入口文件,index.php require_once(DIR_SYSTEM . 'startup.php');//最为重要的一步 start('catalog');//执行了这个方法 ...

  7. java生成缩略图,旋转,水印,截图

    转自:http://rensanning.iteye.com/blog/1545708 感谢,方便自己查看

  8. Mybatis学习—XML映射文件

    总结自 Mybatis官方中文文档 Mapper XML 文件 MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同 ...

  9. ASP.NET MVC 视图学习,纯干货

    最近用MVC专门为自己做了一个网站,用来记录文章心情和日记.加上和同事的一些交流感觉颇深.所以想把13年买的MVC 4高级编程重新看一遍,记录一些东西,以后应该用的到.视图总是被控制器渲染,因为控制器 ...

  10. golang实现mysql数据库备份

    背景 navicat是mysql可视化工具中最棒的,但是,在处理视图的导入导出方面,它是按照视图名称的字母顺序来处理的,若视图存在依赖,在导入过程中就会报错.前面已经用python写了一个,但在使用过 ...