zoukankan      html  css  js  c++  java
  • 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_back
    typedef 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('
    ');
        return 0;
    }
    View Code
  • 相关阅读:
    javaWeb应用 ssm架构 三方外卖系统
    字节跳动2017秋招-前端工程师
    原码补码反码
    MVVM设计模式
    初始化 react 项目
    antd-mobile定制主题
    jeecg-boot 在线代码生成记
    jeecg-boot 开源代码 问题记录
    idea 导入maven 项目一点反应没有,无识别
    layui 搜索加动态添加列
  • 原文地址:https://www.cnblogs.com/lishiyao/p/7296597.html
Copyright © 2011-2022 走看看