题意:
给你一个长度为n的排列,保证n为2的幂次
排列的元素可以看作是在一棵完全二叉树上的叶子结点上,每次操作可以选择一个结点,旋转左右两棵子树
问你最少操作几次可以使得排列升序,如果不行,输出-1
思路:
当且仅当区间[l,mid]的max小于等于区间[mid+1,r]的min时有解
考虑分治,在dfs过程中分裂区间,去看是否满足条件,满足条件的话交换次数++,如果在分裂的时候有一个区间不满足条件,就不可能通过操作使得该序列递增,此时输出-1
Code:
#include <bits/stdc++.h>
using namespace std;
const int mxn=3e5+10,mnf=0x3f3f3f3f;
int n,ans=0;
int a[mxn];
void dfs(int l,int r){
if(l==r) return;
if(a[l]>a[r]) ans++;
int mi1=mnf,mx1=-1,mi2=mnf,mx2=-1;
int mid=l+r>>1;
for(int i=l;i<=mid;i++) mi1=min(mi1,a[i]),mx1=max(mx1,a[i]);
for(int i=mid+1;i<=r;i++) mi2=min(mi2,a[i]),mx2=max(mx2,a[i]);
if(a[l]>a[r]){
if(mi1<mx2) ans=mnf;
}else{
if(mx1>mi2) ans=mnf;
}
dfs(l,mid);
dfs(mid+1,r);
}
void solve(){
ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
dfs(1,n);
if(ans>=mnf) puts("-1");
else printf("%d\n",ans);
}
int main(){
int T;
scanf("%d",&T);
while(T--)solve();
return 0;
}
总结:
不会分治,不知道怎么总结qwq