[BalticOI 2016 Day2] 交换 题解
do_it_tomorrow · · 题解
更好的阅读体验
注意到
假设位置
对于
对于
对于
对于这样的树形结构
应该进行这样的变换:
而不是如上述的贪心策略进行这样的变化:
考虑设
对于上面的情况,我们就只需要考虑
考虑证明这个决策的正确性,不妨设放到
要证决策正确性,只需要证明
要证明
因为
因为
这就证明了
根据定义因为
考虑通过深度优先搜索求解
如果遇到第
如果遇到第
对于第
#include<iostream>
#include<map>
#include<algorithm>
#define ls k*2
#define rs k*2+1
using namespace std;
const int N=4e5+5;
map<int,int> f[N];
int a[N],n;
int solve(int k,int s){
if(f[k].count(s)){
return f[k][s];
}
int ans=0;
if(!a[ls]){
return f[k][s]=k;
}
if(!a[rs]){
if(a[ls]<s){
return f[k][s]=ls;
}
return f[k][s]=k;
}
int A=s,B=a[ls],C=a[rs],v=min({A,B,C});
if(A==v){
return f[k][s]=k;
}
if(B==v){
return f[k][s]=solve(ls,s);
}
int x=solve(ls,min(A,B)),y=solve(rs,min(A,B));
if(s==min(A,B)){
return f[k][s]=min(x,y);
}
if(x<y){
return f[k][s]=solve(rs,s);
}
return f[k][s]=solve(ls,s);
}
void dfs(int k){
if(k>n) return;
int A=a[k],B=a[ls],C=a[rs],v=min({A,B,C});
if(!B){
return;
}
if(!C){
if(B<A){
swap(a[ls],a[k]);
}
return;
}
if(A==v){
dfs(ls),dfs(rs);
return ;
}
if(B==v){
swap(a[k],a[ls]);
dfs(ls),dfs(rs);
return ;
}
a[k]=C;
int x=solve(ls,min(A,B)),y=solve(rs,min(A,B));
a[ls]=min(A,B),a[rs]=max(A,B);
if(y<x){
swap(a[ls],a[rs]);
}
dfs(ls),dfs(rs);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
dfs(1);
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
return 0;
}