zoukankan      html  css  js  c++  java
  • 【AtCoder Regular Contest 080E】Young Maids [堆][线段树]

    Young Maids

    Time Limit: 50 Sec  Memory Limit: 512 MB

    Description

      给定一个排列,每次选出相邻的两个放在队头,要求字典序最小。

    Input

      第一行一个整数n,第二行n个数表示这个排列。

    Output

      n个数表示答案。

    Sample Input

      8
      4 6 3 2 8 5 7 1

    Sample Output

      3 1 2 7 4 6 8 5

    HINT

      n%2=0,2 <= n <= 2e5

    Solution

      倒着考虑。
      我们维护一个小根,堆里面存[l, r, val],表示在区间[l, r]中选择两个元素,第一个元素A的权值为val(保证合法),以val为第一关键字

      那么显然,我们每次选出堆顶进行操作

      显然,若我们取走了A,B(pos[A] < pos[B])[l,r]就被拆成了 [l,A-1], [A+1,B-1], [B+1,r],我们要保证每一个区间长度都是偶数
      那么只要有,pos[A]%2 == pos[l]%2,pos[B]%2 == pos[r]%2
      又由于我们每次减少两个数,所以这样显然可以保证 pos[B]-pos[A]+1 % 2 == 0


      现在问题就是怎么求出A、B具体是那两个数,显然写个线段树维护一下 某段区间内奇数/偶数位置的min_val和所在的pos即可。

    Code

      1 #include<iostream>
      2 #include<string>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cmath>
      8 #include<queue>
      9 using namespace std;
     10 typedef long long s64;
     11 
     12 const int ONE = 200005;
     13 const int INF = 2147483640;
     14 
     15 int get()
     16 {
     17         int res = 1, Q = 1; char c;
     18         while( (c = getchar()) < 48 || c > 57)
     19             if(c == '-') Q = -1;
     20         if(Q) res = c - 48;
     21         while( (c = getchar()) >= 48 && c <= 57)
     22             res = res * 10 + c - 48;
     23         return res * Q;
     24 }
     25 
     26 int n;
     27 int a[ONE];
     28 
     29 struct point
     30 {
     31         int id, val;
     32         friend bool operator <(point a, point b)
     33         {
     34             if(a.val != b.val) return a.val < b.val;
     35             return a.id < b.id;
     36         }
     37 };
     38 point res;
     39 
     40 namespace Seg
     41 {
     42         struct power {point odd, eve;} Node[ONE * 4];
     43         
     44         void Build(int i, int l, int r)
     45         {
     46             Node[i].odd.val = Node[i].eve.val = INF;
     47             if(l == r)
     48             {
     49                 if(l & 1) Node[i].odd = (point){l, a[l]};
     50                 else Node[i].eve = (point){l, a[l]};
     51                 return;
     52             }
     53             int mid = l + r >> 1;
     54             Build(i << 1, l, mid), Build(i << 1 | 1, mid + 1, r);
     55             Node[i].odd = min(Node[i << 1].odd, Node[i << 1 | 1].odd);
     56             Node[i].eve = min(Node[i << 1].eve, Node[i << 1 | 1].eve);
     57         }
     58 
     59         void Query(int i, int l, int r, int L, int R, int opt)
     60         {
     61             if(L <= l && r <= R)
     62             {
     63                 if(opt == 1) res = min(res, Node[i].odd);
     64                 else res = min (res, Node[i].eve);
     65                 return;
     66             }
     67             int mid = l + r >> 1;
     68             if(L <= mid) Query(i << 1, l, mid, L, R, opt);
     69             if(mid + 1 <= R) Query(i << 1 | 1, mid + 1, r, L, R, opt);
     70         }
     71 }
     72 
     73 struct power
     74 {
     75         int l, r, val;
     76         bool operator <(power a) const
     77         {
     78             if(a.val != val) return a.val < val;
     79             return a.l < l;
     80         }
     81 };
     82 priority_queue <power> q;
     83 
     84 point Get(int l, int r, int opt)
     85 {
     86         res = (point){n + 1, INF};
     87         Seg::Query(1, 1, n, l, r, opt);
     88         return res;
     89 }
     90 
     91 void Add(int l, int r)
     92 {
     93         if(l > r) return;
     94         q.push((power){l, r, Get(l, r, l % 2).val});
     95 }
     96 
     97 int main()
     98 {
     99         n = get();
    100         for(int i = 1; i <= n; i++)
    101             a[i] = get();
    102 
    103         Seg::Build(1, 1, n);
    104         Add(1, n);
    105 
    106         for(int i = 1; i <= n / 2; i++)
    107         {
    108             power u = q.top(); q.pop();
    109             point A = Get(u.l, u.r - 1, u.l % 2);
    110             point B = Get(A.id + 1, u.r, u.r % 2);
    111             printf("%d %d ", A.val, B.val);
    112 
    113             Add(u.l, A.id - 1), Add(A.id + 1, B.id - 1), Add(B.id + 1, u.r);
    114         }
    115 }
    View Code
  • 相关阅读:
    Dojo(发音:豆粥)的目标是解决DHTML应用程序长期存在的历史问题
    如何用Fireworks制作图标的透明效果
    2021.09.15膜你赛
    2021.09.14 膜你赛
    2021.08.29 膜你赛
    2021.08.28 膜你赛
    2021.10.06 膜你赛
    2021.09.18 膜你赛
    2021.09.13膜你赛
    2021.10.05膜你赛
  • 原文地址:https://www.cnblogs.com/BearChild/p/7944574.html
Copyright © 2011-2022 走看看