[xsy 2665][LCT]没有上司的舞会

题意:
维护一棵树,初始为空
支持动态加点、求最大独立集
强制在线
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;
}

猜你喜欢

转载自blog.csdn.net/ezoilearner/article/details/84719548
今日推荐