【BZOJ3153】—Sone1(Top-Tree)

传送门

AC这道超级工业题留念

由于LctLct并不能支持子树操作,所以有了这种神奇的数据结构

好像实际上是叫AAAAAA
我也不清楚实际上和TopTreeTop-Tree有啥区别…

大致思想就是在LctLct上每个节点22个儿子变成四个儿子
多的2个作为另外一颗splaysplay的根的左右儿子
这个splaysplay用来维护所有虚儿子

于是子树操作就可以在这个splaysplay上打标记啦
由于各个儿子之间没有大小关系,所以必须全部设在叶子节点,其他点相当于是虚点

据说有9696的常数QwQQwQ

而且不知道为什么
肯定是太naiive而且没有丰富的人生经验
导致LCTLCT里信息维护错了之类的奇怪的问题
要在不必要(雾)的地方加一些东西才能过
比如splaysplay最后得pushuppushup
linklink之后要accessaccess之类的
已经放弃治疗了

具体实现可以看ClarisClaris的博客

代码:

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>  
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int inf=1<<30;
struct tag{
    int mul,add;
    tag(){mul=1,add=0;}
    tag(int _m,int _a){mul=_m,add=_a;}
    inline bool empty(){return mul==1&&!add;}
    friend inline tag operator +(cs tag &a,cs tag &b){
        return tag(a.mul*b.mul,b.mul*a.add+b.add);
    }
    void operator +=(cs tag &a){*this=*this+a;}
    inline int calc(int x){return x*mul+add;}
};
struct node{
    int s,mn,mx,siz;
    node(){s=siz=0,mn=inf,mx=-inf;}
    node(int x){s=mn=mx=x,siz=1;}
    node(int _s,int _mn,int _mx,int _siz){s=_s,mn=_mn,mx=_mx,siz=_siz;}
    friend inline node operator +(cs node &a,cs node &b){
        return node(a.s+b.s,min(a.mn,b.mn),max(a.mx,b.mx),a.siz+b.siz);
    }
    void operator +=(cs node &a){*this=*this+a;}
    friend inline node operator +(cs node &a,tag b){
        return a.siz?node(a.s*b.mul+a.siz*b.add,b.calc(a.mn),b.calc(a.mx),a.siz):a;
    }
    void operator +=(tag a){*this=*this+a;}
};
int rt;
cs int N=200005;
namespace AT{
    int fa[N],son[N][4],stk[N],top,rev[N],in[N],val[N],tot;
    node sc[N],st[N],sa[N];
    tag ct[N],tt[N];
    #define lc(u) son[u][0]
    #define rc(u) son[u][1]
    #define pc(u) son[u][2]
    #define qc(u) son[u][3]
    inline void delet(int u){
        stk[++top]=u;
        lc(u)=rc(u)=pc(u)=qc(u)=rev[u]=in[u]=val[u]=fa[u]=0;
    }
    inline int newnode(){
        int u=top?stk[top--]:++tot;
        in[u]=1;return u;
    }
    inline void initnode(int u,int k){
        st[u]=node(),sa[u]=sc[u]=node(k),val[u]=k;
    }
    inline bool isrt(int u,int t){
        if(!fa[u])return 1;
        if(t)return !in[u]||!in[fa[u]];
        return (lc(fa[u])!=u&&rc(fa[u])!=u)||in[fa[u]]||in[u];
    }
    inline void pushrev(int u){
        swap(lc(u),rc(u)),rev[u]^=1;
    }
    inline void pushnowc(int u,tag k){
        sc[u]+=k,sa[u]=sc[u]+st[u];
        val[u]=k.calc(val[u]),ct[u]+=k;
    }
    inline void pushnowt(int u,tag k,int t){
        st[u]+=k,tt[u]+=k;
        if(!in[u]&&t)pushnowc(u,k);
        else sa[u]=sc[u]+st[u];
    }
    inline void pushdown(int u){
        if(rev[u]){
            if(lc(u))pushrev(lc(u));
            if(rc(u))pushrev(rc(u));
            rev[u]=0;
        }
        if(!in[u]&&!ct[u].empty()){
            if(lc(u))pushnowc(lc(u),ct[u]);
            if(rc(u))pushnowc(rc(u),ct[u]);
            ct[u]=tag();
        }
        if(!tt[u].empty()){
            if(lc(u))pushnowt(lc(u),tt[u],0);
            if(rc(u))pushnowt(rc(u),tt[u],0);
            if(pc(u))pushnowt(pc(u),tt[u],1);
            if(qc(u))pushnowt(qc(u),tt[u],1);
            tt[u]=tag();
        }
    }
    inline void pushup(int u){
        st[u]=node();
        if(lc(u))st[u]+=st[lc(u)];
        if(rc(u))st[u]+=st[rc(u)];
        if(pc(u))st[u]+=sa[pc(u)];
        if(qc(u))st[u]+=sa[qc(u)];
        if(in[u])
            sc[u]=node(),sa[u]=st[u];
        else{
            sc[u]=node(val[u]);
            if(lc(u))sc[u]+=sc[lc(u)];
            if(rc(u))sc[u]+=sc[rc(u)];
            sa[u]=sc[u]+st[u];
        }
    }
    inline int posit(int u){
        if(lc(fa[u])==u)return 0;
        if(rc(fa[u])==u)return 1;
        if(pc(fa[u])==u)return 2;
        if(qc(fa[u])==u)return 3;
        return 4;
    }
    inline void rotate(int v,int t){
        int u=fa[v],pp=(son[u][t+1]==v)+t,z=fa[u],kk;
        fa[v]=z;
        if(z&&(kk=posit(u))!=4)son[z][kk]=v;
        son[u][pp]=son[v][pp^1];
        if(son[v][pp^1])fa[son[v][pp^1]]=u;
        fa[u]=v,son[v][pp^1]=u;
        pushup(u),pushup(v);
    }
    int q[N];
    inline void pushall(int u,int t){
        q[q[0]=1]=u;
        for(int v=u;!isrt(v,t);v=fa[v])q[++q[0]]=fa[v];
        for(int i=q[0];i;i--)pushdown(q[i]);
    }
    inline void splay(int u,int t=0){
        pushall(u,t);
        while(!isrt(u,t)){
            if(!isrt(fa[u],t))
            ((son[fa[fa[u]]][t]==fa[u])^(son[fa[u]][t]==u))?rotate(u,t):rotate(fa[u],t);//????
            rotate(u,t);
        }pushup(u);
    }
    inline int getson(int u,int t){
        pushdown(son[u][t]);return son[u][t];
    }
    inline void setson(int u,int t,int v){
        son[u][t]=v,fa[v]=u;
    }
    inline void add(int u,int v){
        if(!v)return;
        pushdown(u);
        if(!pc(u))return setson(u,2,v);
        if(!qc(u))return setson(u,3,v);
        while(pc(u)&&in[pc(u)])u=getson(u,2);
        int z=newnode();
        setson(z,2,pc(u));
        setson(z,3,v);
        setson(u,2,z);
        splay(z,2);
    }
    inline void del(int u){
        if(!u)return;
        splay(u);
        if(!fa[u])return;
        int v=fa[u];
        if(in[v]){
            pushall(v,2);
            int z=fa[v];
            if(z)setson(z,posit(v),getson(v,posit(u)^1)),splay(z,2);
            delet(v);
        }
        else son[v][posit(u)]=0,splay(v);
        fa[u]=0;
    }
    inline int Fa(int u){
        splay(u);
        if(!fa[u])return 0;
        if(!in[fa[u]])return fa[u];
        int t=fa[u];
        splay(fa[u],2);
        return fa[t];
    }
    inline int access(int u){
        int v=0;
        for(;u;v=u,u=Fa(u)){
            splay(u),del(v);
            add(u,rc(u)),setson(u,1,v);
            pushup(u);
        }
        return v;
    }
    inline void makert(int u){
        access(u),splay(u),pushrev(u);
    }
    inline void link(int u,int v){
        makert(u),access(v),add(v,u),access(u);
    }
    inline void cut(int u){
        access(u),splay(u);
        fa[lc(u)]=0,lc(u)=0;
        pushup(u);
    }
    inline int Lca(int u,int v){
        access(u);return access(v);
    }
    inline void updatec(int u,int v,tag k){
        makert(u),access(v),splay(v);
        pushnowc(v,k),makert(rt);
    }
    inline void updatet(int u,tag k){
        access(u),splay(u);
        val[u]=k.calc(val[u]);
        if(pc(u))pushnowt(pc(u),k,1);
        if(qc(u))pushnowt(qc(u),k,1);
        pushup(u),splay(u);
    }
    inline node queryc(int u,int v){
        makert(u),access(v),splay(v);
        node res=sc[v];makert(rt);return res;
    }
    inline node queryt(int u){
        access(u),splay(u);
        node res=node(val[u]);
        if(pc(u))res+=sa[pc(u)];
        if(qc(u))res+=sa[qc(u)];
        return res;
    }
}
int n,m;
pii e[N];
int main(){
    n=read(),m=read();
    AT::tot=n;
    for(int i=2;i<=n;i++)e[i].fi=read(),e[i].se=read();
    for(int i=1;i<=n;i++)AT::initnode(i,read());
    for(int i=2;i<=n;i++)AT::link(e[i].fi,e[i].se);
    rt=read();
    AT::makert(rt);
    while(m--){
        int op=read();
        int u=read();
        if(op==0){
            int k=read();
            AT::updatet(u,tag(0,k));
        }
        else if(op==1)
            AT::makert(u);
        else if(op==2){
            int v=read(),k=read();
            AT::updatec(u,v,tag(0,k));
        }
        else if(op==3)
            cout<<AT::queryt(u).mn<<'
';
        else if(op==4)
			cout<<AT::queryt(u).mx<<'
';
        else if(op==5){
            int k=read();
            AT::updatet(u,tag(1,k));
        }
        else if(op==6){
            int v=read(),k=read();
            AT::updatec(u,v,tag(1,k));
        }
        else if(op==7){
            int v=read();
            cout<<AT::queryc(u,v).mn<<'
';
        }
        else if(op==8){
            int v=read();
            cout<<AT::queryc(u,v).mx<<'
';
        }
        else if(op==9){
            int v=read();
            if(AT::Lca(u,v)==u)continue;
            AT::cut(u),AT::link(v,u);
            AT::makert(rt);
        }
        else if(op==10){
            int v=read();
            cout<<AT::queryc(u,v).s<<'
';
        }
        else cout<<AT::queryt(u).s<<'
';
    }
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328507.html