AVL 树
题目描述
题解
由于原树
A
V
L
AVL
AVL是一棵二叉查找树,所以我们要让留下的
K
K
K个节点的中序遍历字典序最小,相当于让我们保留下来的所有点的字典序竟可能小。
所以我们可以考虑从
1
−
n
1-n
1−n一直枚举点
i
i
i,看点
i
i
i在不改变编号比它小的点的加入状态的情况下是否能被加入。
如果一个点能被加入,就将它加入,在其前缀已确定的情况下,它加入肯定比它比加入优秀。
显然,如果我们要让这个点加入,我们肯定还要一部分点加入以维护整棵树的
A
V
L
AVL
AVL形态。
如果加入这个点后需要加入以维护形态的点数加上已加入的点数比
K
K
K大,那肯定是不行了。
我们考虑如何计算维护形态的点的数量。
我们定义
d
p
x
,
i
dp_{x,i}
dpx,i表示要让以
x
x
x为根的子树中被选中的点所构成的树是一棵高度为
i
i
i的
A
V
L
AVL
AVL树,我们至少需要加入的未加入的点的数量,
f
i
f_{i}
fi表示一棵高度为
i
i
i的
A
V
L
AVL
AVL最少需要的点数。
显然有转移方程式,
f
i
=
f
i
−
1
+
f
i
−
2
+
1
f_{i}=f_{i-1}+f_{i-2}+1
fi=fi−1+fi−2+1
显然,
d
p
x
,
i
dp_{x,i}
dpx,i最开始为
f
i
f_{i}
fi。
我们再定义
h
x
h_{x}
hx表示根据
x
x
x子树内的情况来看,
h
h
h的高度最低为多少。
由于
d
p
,
h
dp,h
dp,h都需要根据子树内的状况来进行跟更改,所以我们考虑我们每加入一个节点时会对哪些加点造成影响。
显然,只有我们加入节点到根节点的链上会被影响,而
A
V
L
AVL
AVL树的高度是
log
n
\log\,n
logn级别的,所以需要我们更改
d
p
dp
dp值的节点也是
log
n
\log\,n
logn级别的。
h
h
h的转移式:
h
x
=
max
(
h
l
s
o
n
,
h
r
s
o
n
)
+
1
h_{x}=\max(h_{lson},h_{rson})+1
hx=max(hlson,hrson)+1。
h
h
h,由于
h
h
h表示的是最低高度,所以它的最低高度只需要比最低高度最高的儿子的最低高度高即可。
但如果只看最低高度的话不一定是一棵合法的
A
V
L
AVL
AVL树,所以我们显然不能直接将两棵树的大小加在一起。
我们明显可以用
d
p
dp
dp来将整棵子树的最低高度以上的可能的高度所需要的
s
i
z
siz
siz值给存下来,方便转移,有
d
p
dp
dp转移式,
d
p
u
,
i
=
min
(
d
p
l
s
o
n
,
i
−
1
+
d
p
r
s
o
n
,
i
−
1
,
d
p
l
s
o
n
,
i
−
2
+
d
p
r
s
o
n
,
i
−
1
,
d
p
l
s
o
n
,
i
−
1
+
d
p
r
s
o
n
,
i
−
2
)
+
1
dp_{u,i}=\min(dp_{lson,i-1}+dp_{rson,i-1},dp_{lson,i-2}+dp_{rson,i-1},dp_{lson,i-1}+dp_{rson,i-2})+1
dpu,i=min(dplson,i−1+dprson,i−1,dplson,i−2+dprson,i−1,dplson,i−1+dprson,i−2)+1
由于我们的根
r
o
o
t
root
root上面就没有其它节点了,所以只要
d
p
r
o
o
t
,
h
r
o
o
t
dp_{root,h_{root}}
dproot,hroot加上已经加入的节点数是小于
K
K
K的就可以了。
我们的
d
p
dp
dp值是在满足所以已有条件的情况下够着出一种合法情况还需要加入节点的数量,显然,对于
i
<
h
x
i<h_{x}
i<hx的
d
p
x
,
i
dp_{x,i}
dpx,i,它们的值都是极大的,这部分根本不能转移,而如果
i
i
i大于该子树的最大高度的话,也显然是不能转移的,也赋为极大值。
如果当前节点不能加入,我们将刚刚一条链的转移都撤回就行了。
很明显,我们这样一直构造下去得到的情况一定是最小的合法情况。
事实上如果你愿意从上到下时直接维护该子树至少需要多高的话也就没必要维护这个了,在这种情况下,我们是能让较高的子树往左传就往左传,否则就往右传。
但显然
d
p
dp
dp的打法明显是更简单的。
时间复杂度 O ( n log 2 n ) O\left(n\log^2\,n\right) O(nlog2n),但还是可以轻松的过掉。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 500005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int n1=50;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){putchar('\n');while(x>9){putchar((x%10)|'0');x/=10;}putchar(x|'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,K,lson[MAXN],rson[MAXN],dp[30],root,num;
int h[MAXN],tp,hei[MAXN],f[MAXN][30];
int stak,sta[30],st[30][30],sth[30];
bool ans[MAXN],fg;
void sakura(int rt){
if(lson[rt])sakura(lson[rt]);
if(rson[rt])sakura(rson[rt]);
hei[rt]=max(hei[lson[rt]],hei[rson[rt]])+1;
}
void insert(int rt,int x){
sta[++stak]=rt;sth[stak]=h[rt];
for(int i=0;i<=hei[rt];i++)st[stak][i]=f[rt][i];
if(rt==x){
f[rt][0]=n+1;f[rt][1]=f[lson[rt]][0]+f[rson[rt]][0];
h[rt]=max(h[lson[rt]],h[rson[rt]])+1;
for(int i=0;i<=hei[rt];i++)f[rt][i]=n+1;
for(int i=h[rt];i<=hei[rt];i++)
f[rt][i]=min(f[lson[rt]][i-1]+f[rson[rt]][i-1],f[rt][i]),
f[rt][i]=min(f[lson[rt]][i-1]+f[rson[rt]][i-2],f[rt][i]),
f[rt][i]=min(f[lson[rt]][i-2]+f[rson[rt]][i-1],f[rt][i]);
return ;
}
if(x<rt)insert(lson[rt],x);else insert(rson[rt],x);
h[rt]=max(h[lson[rt]],h[rson[rt]])+1;
for(int i=0;i<=hei[rt];i++)f[rt][i]=n+1;
for(int i=h[rt];i<=hei[rt];i++)
f[rt][i]=min(f[lson[rt]][i-1]+f[rson[rt]][i-1]+(rt>x),f[rt][i]),
f[rt][i]=min(f[lson[rt]][i-1]+f[rson[rt]][i-2]+(rt>x),f[rt][i]),
f[rt][i]=min(f[lson[rt]][i-2]+f[rson[rt]][i-1]+(rt>x),f[rt][i]);
}
signed main(){
freopen("avl.in","r",stdin);
freopen("avl.out","w",stdout);
read(n);read(K);dp[1]=1;dp[2]=2;int tim=0;
for(int i=3;i<=28;i++)dp[i]=dp[i-1]+dp[i-2]+1;
for(int i=1;i<=n;i++){
int x;read(x);if(x<0){root=i;continue;}
if(i<x)lson[x]=i;else rson[x]=i;
}
sakura(root);
for(int i=0;i<=n;i++)
for(int j=0;j<=28;j++)f[i][j]=n+1;
f[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=hei[i];j++)f[i][j]=dp[j];
for(int i=1;i<=n;i++){
stak=0;insert(root,i);
if(num+1+f[root][h[root]]>K){
while(stak){
h[sta[stak]]=sth[stak];
for(int j=0;j<=hei[sta[stak]];j++)
f[sta[stak]][j]=st[stak][j];
stak--;
}
}
else ans[i]=1,num++;
}
for(int i=1;i<=n;i++)assert(Fabs(h[lson[i]]-h[rson[i]])<=1);
for(int i=1;i<=n;i++)printf("%d",ans[i]);puts("");
return 0;
}