题意:
维护一棵树,初始为空
支持动态加点、求最大独立集
强制在线
n <= 2 * 10^5
解法:
考虑树是一条链的情况。
显然,用一棵线段树,维护左右两端分别选不选的最优解即可。
这里我们弄个LCT就行了,注意一下虚子树的信息即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int inf=1e9;
int n,type;
#define Maxn 300010
struct Node{
int son[2],fa;
int f[2][2];
int sum[2];
}tree[Maxn];
inline bool isrt(int k){return tree[tree[k].fa].son[0]!=k&&tree[tree[k].fa].son[1]!=k;}
inline bool who(int k){return tree[tree[k].fa].son[1]==k;}
inline void push_up(int k){
int ls=tree[k].son[0],rs=tree[k].son[1];
if(!ls&&!rs){
tree[k].f[0][0]=tree[k].sum[0];
tree[k].f[1][1]=tree[k].sum[1];
tree[k].f[0][1]=tree[k].f[1][0]=-inf;
return;
}
if(!ls){
for(int i=0;i<2;++i){
tree[k].f[0][i]=tree[k].sum[0]+max(tree[rs].f[0][i],tree[rs].f[1][i]);
tree[k].f[1][i]=tree[k].sum[1]+tree[rs].f[0][i];
}
return;
}
if(!rs){
for(int i=0;i<2;++i){
tree[k].f[i][0]=tree[k].sum[0]+max(tree[ls].f[i][0],tree[ls].f[i][1]);
tree[k].f[i][1]=tree[k].sum[1]+tree[ls].f[i][0];
}
return;
}
for(int i=0;i<2;++i)
for(int j=0;j<2;++j){
tree[k].f[i][j]=max(tree[ls].f[i][0],tree[ls].f[i][1])+tree[k].sum[0]+max(tree[rs].f[0][j],tree[rs].f[1][j]);
tree[k].f[i][j]=max(tree[k].f[i][j],tree[ls].f[i][0]+tree[k].sum[1]+tree[rs].f[0][j]);
}
}
inline void upd(int k,int x,int ty){
tree[k].sum[0]+=max(max(tree[x].f[0][0],tree[x].f[0][1]),max(tree[x].f[1][0],tree[x].f[1][1]))*ty;
tree[k].sum[1]+=max(tree[x].f[0][0],tree[x].f[0][1])*ty;
}
inline void rot(int k){
int f=tree[k].fa,ff=tree[f].fa;
int dir=who(k);
tree[k].fa=ff;
if(!isrt(f))tree[ff].son[who(f)]=k;
tree[f].son[dir]=tree[k].son[dir^1];tree[tree[k].son[dir^1]].fa=f;
tree[k].son[dir^1]=f;tree[f].fa=k;
push_up(f);
push_up(k);
}
inline void Splay(int u){
for(int f;!isrt(u);rot(u))
if(!isrt(f=tree[u].fa))rot(who(f)==who(u)?f:u);
}
inline void access(int u){
for(int t=0;u;t=u,u=tree[u].fa){
Splay(u);
upd(u,tree[u].son[1],1);
upd(u,t,-1);
tree[u].son[1]=t;
push_up(u);
}
}
inline int Insert(int u,int k){
tree[u].sum[1]=1;
push_up(u);
tree[u].fa=k;
access(k);
Splay(k);
upd(k,u,1);
push_up(k);
return max(max(tree[k].f[0][0],tree[k].f[0][1]),max(tree[k].f[1][0],tree[k].f[1][1]));
}
inline void rd(int &x){
x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
}
int main(){
rd(n);rd(type);
n++;
int x,Ans=0;
tree[1].sum[1]=1;
push_up(1);
for(int i=2;i<=n;++i){
rd(x);
x=(x^(type*Ans))+1;
Ans=Insert(i,x);
printf("%d\n",Ans);
}
return 0;
}