题目大意
只有加点操作,动态维护树的最大独立集
题解
考虑LCT,对于一个点x,s[x][0/1]表示x选或不选时不与他在同一条链上的儿子的DP值,f[x][0/1][0/1]表示splay中x维护的这一个区间最左端选或不选以及最右端选或不选的DP值,只要在切掉splay的边或连接时维护s就好了
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<bitset>
#include<map>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long LL;
typedef double db;
int get(){
char ch;
while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');
if (ch=='-'){
int s=0;
while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
return -s;
}
int s=ch-'0';
while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
return s;
}
const int N = 300010;
struct node{
int s[2];
int f[2][2];
int* operator [](int x){return f[x];}
}tree[N];
int fa[N];
int s[N][2];
int n;
int pd(int x){
if (x==tree[fa[x]].s[0])return 0;
if (x==tree[fa[x]].s[1])return 1;
return -1;
}
void update(int x){
int ls=tree[x].s[0],rs=tree[x].s[1];
if (!ls&&!rs){
tree[x][0][1]=tree[x][1][0]=0;
tree[x][0][0]=s[x][0];
tree[x][1][1]=s[x][1]+1;
return;
}
if (ls&&rs)
fo(a,0,1)
fo(b,0,1)
tree[x][a][b]=max(tree[ls][a][0]+s[x][1]+tree[rs][0][b]+1,max(tree[ls][a][0],tree[ls][a][1])+s[x][0]+max(tree[rs][0][b],tree[rs][1][b]));
else
if (ls){
fo(a,0,1){
tree[x][a][1]=tree[ls][a][0]+s[x][1]+1;
tree[x][a][0]=max(tree[ls][a][0],tree[ls][a][1])+s[x][0];
}
}
else{
fo(b,0,1){
tree[x][1][b]=tree[rs][0][b]+s[x][1]+1;
tree[x][0][b]=s[x][0]+max(tree[rs][0][b],tree[rs][1][b]);
}
}
}
void split(int x){
int y=tree[x].s[1];
s[x][0]+=max(max(tree[y][0][0],tree[y][0][1]),max(tree[y][1][0],tree[y][1][1]));
s[x][1]+=max(tree[y][0][0],tree[y][0][1]);
tree[x].s[1]=0;
update(x);
}
void merge(int x,int y){
s[x][0]-=max(max(tree[y][0][0],tree[y][0][1]),max(tree[y][1][0],tree[y][1][1]));
s[x][1]-=max(tree[y][0][0],tree[y][0][1]);
tree[x].s[1]=y;
update(x);
}
void rotate(int x){
int y=fa[x],z=fa[y];
int tx=pd(x),ty=pd(y);
if (ty!=-1)tree[z].s[ty]=x;
fa[x]=z;
if (tree[x].s[tx^1])fa[tree[x].s[tx^1]]=y;
tree[y].s[tx]=tree[x].s[tx^1];
tree[x].s[tx^1]=y;
fa[y]=x;
update(y);
update(x);
if (ty!=-1)update(z);
}
void splay(int x){
while(pd(x)!=-1){
if (pd(fa[x])!=-1){
if (pd(fa[x])==pd(x))rotate(fa[x]);
else rotate(x);
}
rotate(x);
}
}
void access(int x){
splay(x);
if (tree[x].s[1])split(x);
while(fa[x]){
int y=fa[x];
splay(y);
if (tree[y].s[1])split(y);
merge(y,x);
update(x);
x=y;
}
}
int main(){
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
n=get();
int ty=get();
int ans=0;
tree[1][1][1]=1;
tree[1][0][0]=0;
fo(i,2,n+1){
int x=get();
x=x^(ans*ty);
x++;
fa[i]=x;
access(x);
splay(x);
tree[i][1][1]=1;
tree[i][0][0]=0;
s[x][0]++;
update(x);
fo(a,0,1)
fo(b,0,1)
ans=max(ans,tree[x][a][b]);
printf("%d\n",ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}