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; }