首页 > 代码库 > Atcoder arc080E Young Maids(线段树+优先队列)

Atcoder arc080E Young Maids(线段树+优先队列)

给出一个n排列,每次可以选择相邻的两个数字放在新的排列首部,问最后形成的新的排列字典序最小是?

 

考虑新排列的第一个数字,则应是下标为奇数的最小数,下标不妨设为i。第二个数字应该下标大于i且为偶数的最小数,不妨设为j。

那么这样就将[1,n]新分割成了三个区间[1,i-1],[i+1,j-1],[j+1,n]。

用线段树实现查询操作。用优先队列维护区间的最优值。

时间复杂度O(nlogn).

 

技术分享
# include <cstdio># include <cstring># include <cstdlib># include <iostream># include <vector># include <queue># include <stack># include <map># include <bitset># include <set># include <cmath># include <algorithm>using namespace std;# define lowbit(x) ((x)&(-x))# define pi acos(-1.0)# define eps 1e-8# define MOD 1000000007# define INF 1000000000# define mem(a,b) memset(a,b,sizeof(a))# define FOR(i,a,n) for(int i=a; i<=n; ++i)# define FDR(i,a,n) for(int i=a; i>=n; --i)# define bug puts("H");# define lch p<<1,l,mid# define rch p<<1|1,mid+1,r# define mp make_pair# define pb push_backtypedef pair<int,int> PII;typedef vector<int> VI;# pragma comment(linker, "/STACK:1024000000,1024000000")typedef long long LL;inline int Scan() {    int x=0,f=1; char ch=getchar();    while(ch<0||ch>9){if(ch==-) f=-1; ch=getchar();}    while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();}    return x*f;}inline void Out(int a) {    if(a<0) {putchar(-); a=-a;}    if(a>=10) Out(a/10);    putchar(a%10+0);}const int N=200005;//Code begin....struct qnode{   int l, r, vl, vr;   qnode(int _l=0, int _r=0, int _vl=0, int _vr=0):l(_l),r(_r),vl(_vl),vr(_vr){}   bool operator<(const qnode &m)const{return vl>m.vl;}};priority_queue<qnode>que;struct Seg{int odd, even;}seg[N<<3];int a[N], id[N];VI ans;void push_up(int p){    seg[p].even=min(seg[p<<1].even, seg[p<<1|1].even);    seg[p].odd=min(seg[p<<1].odd, seg[p<<1|1].odd);}void init(int p, int l, int r){    if (l<r) {        int mid=(l+r)>>1;        init(lch); init(rch); push_up(p);    }    else {        if (l&1) seg[p].even=a[l], seg[p].odd=INF;        else seg[p].odd=a[l], seg[p].even=INF;    }}int query(int p, int l, int r, int L, int R, int flag){    if (L>r||R<l) return INF;    if (L<=l&&R>=r) return flag?seg[p].even:seg[p].odd;    else {        int mid=(l+r)>>1;        return min(query(lch,L,R,flag),query(rch,L,R,flag));    }}int main (){    int n, x, y, l, r, ll;    qnode tmp;    scanf("%d",&n);    FOR(i,1,n) scanf("%d",a+i), id[a[i]]=i;    init(1,1,n);    x=query(1,1,n,1,n,1); l=id[x]; y=query(1,1,n,l+1,n,0);    que.push(qnode(1,n,x,y));    FOR(i,1,n/2) {        tmp=que.top(); que.pop();        ans.pb(tmp.vl); ans.pb(tmp.vr);        l=id[tmp.vl]; r=id[tmp.vr];        if (tmp.l<l-1) {            x=query(1,1,n,tmp.l,l-1,tmp.l&1); ll=id[x]; y=query(1,1,n,ll+1,l-1,(l-1)&1);            que.push(qnode(tmp.l,l-1,x,y));        }        if (l+1<r-1) {            x=query(1,1,n,l+1,r-1,(l+1)&1); ll=id[x]; y=query(1,1,n,ll+1,r-1,(r-1)&1);            que.push(qnode(l+1,r-1,x,y));        }        if (r+1<tmp.r) {            x=query(1,1,n,r+1,tmp.r,(r+1)&1); ll=id[x]; y=query(1,1,n,ll+1,tmp.r,tmp.r&1);            que.push(qnode(r+1,tmp.r,x,y));        }    }    for (int i=0; i<ans.size(); ++i) printf(i==0?"%d":" %d",ans[i]);    putchar(\n);    return 0;}
View Code

 

Atcoder arc080E Young Maids(线段树+优先队列)