没有上司的舞会
Description
一开始整棵树只有 1 1 1号点,接下来每次动态添加一条树边,求每个时刻树的最大独立集。
Data Constraints
n ≤ 3 ∗ 1 0 5 n \leq 3*10^5 n≤3∗105
Solution
有
l
c
t
lct
lct维护。
设
f
i
,
0
/
1
,
0
/
1
f_{i,0/1,0/1}
fi,0/1,0/1表示
i
i
i节点在
s
p
l
a
y
splay
splay所代表的区间中左端/右端 选/不选的最大贡献,再设
g
i
,
0
/
1
g_{i,0/1}
gi,0/1表示
i
i
i节点选/不选时,自身与轻儿子贡献的最大值。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)
using namespace std;
typedef long long ll;
const ll N=31e4;
int f[N][2][2],g[N][2];
int ls[N],rs[N],fa[N],tfa[N],tag[N],d[N];
int n,typ,ff;
inline int min(int a,int b)
{return a<b?a:b;}
inline int max(int a,int b)
{return a>b?a:b;}
inline void updata(int o)
{
int l=ls[o],r=rs[o];
f[o][1][1]=g[o][1]; f[o][0][0]=g[o][0]; f[o][0][1]=f[o][1][0]=0;
if(l){
f[o][0][0]=max(f[l][0][1],f[l][0][0])+g[o][0];
f[o][1][0]=max(f[l][1][1],f[l][1][0])+g[o][0];
f[o][0][1]=f[l][0][0]+g[o][1];
f[o][1][1]=f[l][1][0]+g[o][1];
}
if(r){
int g[2][2];
fo(i,0,1)fo(l,0,1){
g[i][l]=f[o][i][0]+f[r][0][l];
g[i][l]=max(g[i][l],f[o][i][0]+f[r][1][l]);
g[i][l]=max(g[i][l],f[o][i][1]+f[r][0][l]);
}
fo(i,0,1)fo(l,0,1)f[o][i][l]=g[i][l];
}
}
inline void rev(int o)
{swap(f[o][0][1],f[o][1][0]);}
inline void down(int o)
{
swap(ls[ls[o]],rs[ls[o]]);
swap(ls[rs[o]],rs[rs[o]]);
rev(ls[o]); rev(rs[o]);
tag[ls[o]]^=1; tag[rs[o]]^=1;
tag[o]=0;
}
inline void down_tag(int o)
{
int v=0,k=o;
for(;k;k=fa[k])d[++v]=k;
fd(i,v,1)if(tag[d[i]])down(d[i]);
}
inline int pd(int o)
{return ls[fa[o]]==o;}
inline void rotate(int o)
{
int k=fa[o];
fa[o]=fa[k]; fa[k]=o; tfa[o]=tfa[k]; tfa[k]=0;
if(ls[fa[o]]==k)ls[fa[o]]=o;else rs[fa[o]]=o;
if(ls[k]==o)ls[k]=rs[o],fa[ls[k]]=k,rs[o]=k;
else rs[k]=ls[o],fa[rs[k]]=k,ls[o]=k;
ls[0]=rs[0]=fa[0]=tfa[0]=0;
updata(k); updata(o);
}
inline void splay(int x,int y)
{
down_tag(x);
while(fa[x]!=y){
if(fa[fa[x]]!=y)
if(pd(fa[x])==pd(x))rotate(fa[x]);
rotate(x);
}
}
inline void access(int o)
{
splay(o,0);
if(rs[o]){
tfa[rs[o]]=o;
fa[rs[o]]=0;
int k1=max(f[rs[o]][0][1],f[rs[o]][0][0]);
int k2=max(f[rs[o]][1][0],f[rs[o]][1][1]);
g[o][0]+=max(k1,k2);
g[o][1]+=k1;
rs[o]=0;
updata(o);
}
while(tfa[o]){
int k=o;
o=tfa[o];
splay(o,0);
if(rs[o]){
tfa[rs[o]]=o;
fa[rs[o]]=0;
int k1=max(f[rs[o]][0][1],f[rs[o]][0][0]);
int k2=max(f[rs[o]][1][0],f[rs[o]][1][1]);
g[o][0]+=max(k1,k2);
g[o][1]+=k1;
}
rs[o]=k; fa[k]=o; tfa[k]=0;
int k1=max(f[k][0][1],f[k][0][0]);
int k2=max(f[k][1][0],f[k][1][1]);
g[o][0]=g[o][0]-max(k1,k2);
g[o][1]=g[o][1]-k1;
updata(o);
}
}
inline void makeroot(int o)
{
access(o);
splay(o,0);
tag[o]^=1;
swap(ls[o],rs[o]);
rev(o);
}
int main()
{
scanf("%d%d",&n,&typ);
int ans=0;
g[1][1]=1; f[1][1][1]=1;
fo(i,2,n+1){
scanf("%d",&ff);
ff=ff^(typ*ans);
++ff;
makeroot(ff);
++g[ff][0];
tfa[i]=ff; fa[i]=0;
updata(ff);
f[i][0][0]=f[i][0][1]=f[i][1][0]=0; f[i][1][1]=1;
g[i][1]=1; g[i][0]=0;
ans=0;
fo(l,0,1)fo(j,0,1)ans=max(ans,f[ff][l][j]);
printf("%d\n",ans);
}
}