AtCoder Regular Contest 080 E - Young Maids

地址:http://arc080.contest.atcoder.jp/tasks/arc080_c

题目:

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.
  • 2≤N≤2×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.

 

思路:

  不想自己写了,结合我代码看官方题解吧。

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 #define MP make_pair
  6 #define PB push_back
  7 typedef long long LL;
  8 typedef pair<int,int> PII;
  9 const double eps=1e-8;
 10 const double pi=acos(-1.0);
 11 const int K=3e5+7;
 12 const int mod=1e9+7;
 13 
 14 int n,vb[4*K],vc[4*K],ff[4*K],hs[K],a[K];
 15 //vb奇数,vc偶数
 16 void push_down(int o)
 17 {
 18     if(ff[o])
 19     {
 20         swap(vb[o<<1],vc[o<<1]);
 21         swap(vb[o<<1|1],vc[o<<1|1]);
 22         ff[o<<1]^=ff[o],ff[o<<1|1]^=ff[o];
 23         ff[o]=0;
 24     }
 25 }
 26 void update(int o,int l,int r,int pos,int x)
 27 {
 28     if(l==r)
 29     {
 30         if(pos&1) vb[o]=x,vc[o]=K;
 31         else vb[o]=K,vc[o]=x;
 32         return ;
 33     }
 34     int mid=l+r>>1;
 35     push_down(o);
 36     if(pos<=mid) update(o<<1,l,mid,pos,x);
 37     else update(o<<1|1,mid+1,r,pos,x);
 38     vb[o]=min(vb[o<<1],vb[o<<1|1]);
 39     vc[o]=min(vc[o<<1],vc[o<<1|1]);
 40 }
 41 void update2(int o,int l,int r,int nl,int nr)
 42 {
 43     if(l==nl&&r==nr)
 44     {
 45         ff[o]^=1;swap(vb[o],vc[o]);
 46         return ;
 47     }
 48     int mid=l+r>>1;
 49     push_down(o);
 50     if(nr<=mid) update2(o<<1,l,mid,nl,nr);
 51     else if(nl>mid) update2(o<<1|1,mid+1,r,nl,nr);
 52     else update2(o<<1,l,mid,nl,mid),update2(o<<1|1,mid+1,r,mid+1,nr);
 53     vb[o]=min(vb[o<<1],vb[o<<1|1]);
 54     vc[o]=min(vc[o<<1],vc[o<<1|1]);
 55 }
 56 int query(int o,int l,int r,int nl,int nr)
 57 {
 58     if(l==nl&&r==nr)return vb[o];
 59     int mid=l+r>>1;
 60     push_down(o);
 61     if(nr<=mid) return query(o<<1,l,mid,nl,nr);
 62     else if(nl>mid) return query(o<<1|1,mid+1,r,nl,nr);
 63     else return min(query(o<<1,l,mid,nl,mid),query(o<<1|1,mid+1,r,mid+1,nr));
 64 }
 65 struct node
 66 {
 67     int l,r,pl,pr;
 68     node(){}
 69     node(int i,int j,int p,int q){l=i,r=j,pl=p,pr=q;}
 70     bool operator<(const node &ta)const
 71     {
 72         if(a[pl]==a[ta.pl]) return a[pr]>a[ta.pr];
 73         return a[pl]>a[ta.pl];
 74     }
 75 };
 76 node sc(int l,int r)
 77 {
 78     int x=query(1,1,n,l,r);
 79     update(1,1,n,hs[x],K);
 80     if(hs[x]+1<=r)
 81         update2(1,1,n,hs[x]+1,r);
 82     int y=query(1,1,n,hs[x]+1,r);
 83     update(1,1,n,hs[y],K);
 84     if(hs[y]+1<=r)
 85         update2(1,1,n,hs[y]+1,r);
 86     return node(l,r,hs[x],hs[y]);
 87 }
 88 priority_queue<node>q;
 89 int main(void)
 90 {
 91     scanf("%d",&n);
 92     for(int i=1,mx=n*4;i<=mx;i++) vb[i]=vc[i]=K;
 93     for(int i=1;i<=n;i++)
 94     {
 95         scanf("%d",a+i);
 96         update(1,1,n,i,a[i]);
 97         hs[a[i]]=i;
 98     }
 99     q.push(sc(1,n));
100     while(q.size())
101     {
102         node tmp=q.top();
103         q.pop();
104         printf("%d %d ",a[tmp.pl],a[tmp.pr]);
105         if(tmp.pl-1>tmp.l) q.push(sc(tmp.l,tmp.pl-1));
106         if(tmp.pl+1<tmp.pr-1) q.push(sc(tmp.pl+1,tmp.pr-1));
107         if(tmp.pr+1<tmp.r) q.push(sc(tmp.pr+1,tmp.r));
108     }
109     return 0;
110 }

 

 

转载于:https://www.cnblogs.com/weeping/p/7296619.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值