AtCoder Regular Contest 080 E - Young Maids(线段树+优先队列)

E - Young Maids


Time limit : 2sec / Memory limit : 256MB

Score : 800 points

Problem Statement

Let N be a positive even number.

We have a permutation of (1,2,…,N)p=(p1,p2,…,pN). Snuke is constructing another permutation of (1,2,…,N)q, following the procedure below.

First, let q be an empty sequence. Then, perform the following operation until p becomes empty:

  • Select two adjacent elements in p, and call them x and y in order. Remove x and y from p (reducing the length of p by 2), and insert x and y, preserving the original order, at the beginning of q.

When p becomes empty, q will be a permutation of (1,2,…,N).

Find the lexicographically smallest permutation that can be obtained as q.

Constraints

  • N is an even number.
  • 2N2×105
  • p is a permutation of (1,2,…,N).

Input

Input is given from Standard Input in the following format:

N
p1 p2  pN

Output

Print the lexicographically smallest permutation, with spaces in between.


Sample Input 1

Copy
4
3 2 4 1

Sample Output 1

Copy
3 1 2 4

The solution above is obtained as follows:

pq
(3,2,4,1)()
(3,1)(2,4)
()(3,1,2,4)

Sample Input 2

Copy
2
1 2

Sample Output 2

Copy
1 2

Sample Input 3

Copy
8
4 6 3 2 8 5 7 1

Sample Output 3

Copy
3 1 2 7 4 6 8 5

The solution above is obtained as follows:

pq
(4,6,3,2,8,5,7,1)()
(4,6,3,2,7,1)(8,5)
(3,2,7,1)(4,6,8,5)
(3,1)(2,7,4,6,8,5)
()(3,1,2,7,4,6,8,5)


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e6+10;
int a[N],  pos[N], sum1[N<<2], sum2[N<<2], n,  ans;
// 1 奇数 , 2 偶数
typedef pair<int,int> pi;
struct node
{
    int first,second,l,r;
    bool operator <(const node &A)const
    {
        return A.first<first;
    }
};
vector<node>p;
void build(int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%d", &a[l]);
        if(l&1)   sum1[rt]=a[l],sum2[rt]=0x3f3f3f3f;
        else sum1[rt]=0x3f3f3f3f,sum2[rt]=a[l];
        pos[a[l]]=l;
        return ;
    }
    int mid=(l+r)/2;
    build(l,mid,rt*2);
    build(mid+1,r,rt*2+1);
    sum1[rt]=min(sum1[rt<<1],sum1[rt<<1|1]);
    sum2[rt]=min(sum2[rt<<1],sum2[rt<<1|1]);
    return ;
}
int query1(int l,int r,int rt,int L,int R)
{
    if(L<=l&&R>=r)  return sum1[rt];
    int mid=(l+r)/2;
    int ans=0x3f3f3f3f;
    if(L<=mid) ans=min(ans,query1(l,mid,rt*2,L,R));
    if(R>mid) ans=min(ans,query1(mid+1,r,rt*2+1,L,R));
    return ans;
}
int query2(int l,int r,int rt,int L,int R)
{
    if(L<=l&&R>=r)  return sum2[rt];
    int mid=(l+r)/2;
    int ans=N+1;
    if(L<=mid) ans=min(ans,query2(l,mid,rt*2,L,R));
    if(R>mid) ans=min(ans,query2(mid+1,r,rt*2+1,L,R));
    return ans;
}
priority_queue<node>q;

int main()
{
    scanf("%d", &n);
    build(1,n,1);
    int x=query1(1,n,1,1,n);
    int y=query2(1,n,1,pos[x]+1,n);
    q.push((node){x,y,1,n});
    for(int i=1;i<=n/2;i++)
    {
        node tmp=q.top();q.pop();
        p.push_back(node{tmp.first,tmp.second,0,0});
        int al=pos[tmp.first], ar=pos[tmp.second];
        if(tmp.l<al-1)
        {
            if(tmp.l&1)
            {
                x=query1(1,n,1,tmp.l,al-1);
                y=query2(1,n,1,pos[x]+1,al-1);
            }
            else
            {
                x=query2(1,n,1,tmp.l,al-1);
                y=query1(1,n,1,pos[x]+1,al-1);
            }
            q.push(node{x,y,tmp.l,al-1});
        }
        if(al<ar-1)
        {
            if((al+1)&1)
            {
                x=query1(1,n,1,al+1,ar-1);
                y=query2(1,n,1,pos[x]+1,ar-1);
            }
            else
            {
                x=query2(1,n,1,al+1,ar-1);
                y=query1(1,n,1,pos[x]+1,ar-1);
            }
            q.push(node{x,y,al+1,ar-1});
        }
        if(ar<tmp.r-1)
        {
            if((ar+1)&1)
            {
                x=query1(1,n,1,ar+1,tmp.r);
                y=query2(1,n,1,pos[x]+1,tmp.r);
            }
            else
            {
                x=query2(1,n,1,ar+1,tmp.r);
                y=query1(1,n,1,pos[x]+1,tmp.r);
            }
            q.push(node{x,y,ar+1,tmp.r});
        }
    }
    for(int i=0; i<p.size(); i++)
    {
        if(i==p.size()-1)printf("%d %d\n",p[i].first,p[i].second);
        else printf("%d %d ",p[i].first,p[i].second);
    }
    return 0;
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值