AtCoder Regular Contest 080 E - Young Maids

RMQ变形一下,dp[0,1][i][j]代表为奇偶时的最小数的下标,每次在给定区间查找 奇数位最小偶数位最小的数对 或者 偶数位最小奇数位最小的数对。

再求一下左区间和右区间和数对内区间,三个区间无序,但是父区间和子区间是有序的,用优先队列对树排下序是一个很好的选择。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<cmath>
#include<set>
#include<stack>
#define ll long long
#define pb push_back
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define cls(name,x) memset(name,x,sizeof(name))//0或-1
#define fs first
#define sc second
#define mp make_pair
#define L(x) (1<<x)
#define next Next
using namespace std;
const int inf=1e9+10;
const ll llinf=1e16+10;
const int maxn=2e5+10;
const int maxm=1e3+10;
const int mod=1e9+7;
int n;
int A[maxn];
int dp[2][maxn][30];
int cnt;
struct node
{
    int x,y,t1,t2,t3;
    bool friend operator < (const node &a,const node &b)
    {
        return a.x>b.x;
    }
}ans[maxn];
void init()
{
    for(int i=1;i<=n;i++)
        dp[i%2][(i+1)/2][0]=i;
    for(int op=0;op<=1;op++)
        for(int j=1;L(j)<=(n+1)/2;j++)
            for(int i=1;i+L(j)-1<=(n+1)/2;i++)
            {
                int t1=dp[op][i][j-1],t2=dp[op][i+(1<<(j-1))][j-1];
                if(A[t1]<A[t2])
                    dp[op][i][j]=t1;
                else dp[op][i][j]=t2;
            }
}
int querry(int L,int R,int op)
{
    if(op==1)
    {
        L=(L+1)/2;
        R=(R+1)/2;
    }
    else
    {
        L=(L)/2;
        R=(R)/2;
    }
    int t1,t2;
    int x=(int)(log(R-L+1.0)/log(2.0));
    t1=dp[op][L][x];
    t2=dp[op][R-L(x)+1][x];
    if(A[t1]<A[t2])
        return t1;
    else return t2;
}
int solve(int l,int r,int k)
{
    int st=querry(l,r,l%2);
    int ed=querry(st+1,r,(st+1)%2);
    int temp=cnt++;
    ans[temp].x=A[st];
    ans[temp].y=A[ed];
    ans[temp].t1=ans[temp].t2=ans[temp].t3=-1;
    if(st>l)
        ans[temp].t1=solve(l,st-1,k+1);
    if(ed<r)
        ans[temp].t2=solve(ed+1,r,k+1);
    if(ed-st>=3)
        ans[temp].t3=solve(st+1,ed-1,k+1);
    return temp;
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        cnt=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&A[i]);
        init();
        solve(1,n,1);
        priority_queue<node> Q;
        Q.push(ans[0]);
        while(!Q.empty())
        {
            node t=Q.top();
            Q.pop();
            printf("%d %d",t.x,t.y);
            if(t.t1!=-1) Q.push(ans[t.t1]);
            if(t.t2!=-1) Q.push(ans[t.t2]);
            if(t.t3!=-1) Q.push(ans[t.t3]);
            if(!Q.empty()) printf(" ");
            else printf("\n");
        }
        /*for(int i=0;i<n/2;i++)
            printf("%d %d %d\n",i,ans[i].x,ans[i].y);*/
    }
    return 0;
}

 

posted @ 2017-08-08 17:13  爱种树的码农  阅读(152)  评论(0编辑  收藏  举报