LCT求调(WA10#
查看原帖
LCT求调(WA10#
1011287
LIGASIA楼主2024/1/10 18:42

rt

可能马蜂比较独特(自认为还性

#include<bits/stdc++.h>
using namespace std;
void solve();
int main(){solve();}
#define int long long
class LCT{
/*----------------- 节点 ------------------*/
struct Node
{
    int Fro;//父亲指向
    int To[2];//左右儿子
    int Rev;//翻转标记
    int Tag;//权值标记
    int Sum;//路径权值和
    int Siz;//辅助树上子树大小
    int Val;//点权
    inline void Rever(){
        To[0]^=To[1];
        To[1]^=To[0];
        To[0]^=To[1];
        Rev^=1;
    }
}T[500000];
/* ----------- 一般数据结构函数 ----------- */
void PushDown(int rt);
void PushUp(int rt);
/* 一----------- Splay树函数 -----------一 */
//#define catch(rt)  //获取 [rt] 是父亲的哪个儿子
void Rotate(int rt);//将 [rt] 向上旋转一层的操作
public:void Splay(int rt);//通过和 Rotate 操作联动实现把 [rt] 旋转到 当前 Splay 的根
/*--------------- NEW -------------------*/
/*^只有此操作是必须实现的,其他操作视题目而实现*/
int Access(int rt);//把从根到 [rt] 的所有点放在一条实链里,使根到 [rt] 成为一条实路径,并且在同一棵 Splay 里。
/*其他的LCT的独有函数*/
bool IsRoot(int rt);//判断 [rt] 是否是所在树的根
void Update(int rt);//在 Access 操作之后,递归地从上到下 PushDown 更新信息
void TurnRoot(int rt);//使 [rt] 点成为其所在树的根
public:
int query(int kl);//访问 T->sum 本题要用
void Cut(int x,int y);//把 [x, y] 两点间边删掉
void Link(int x,int y);//在 [x, y] 两点间连一条边
int Find(int x);//找到 [x] 所在树的根节点编号
void Fix(int kl,int val);//修改 [kl] 的点权为 [val] 
void Split(int x,int y);//提取出 [x, y] 间的路径,方便做区间操作
};
/*---------------- Push -----------------*/
void LCT::PushUp(int rt){
    T[rt].Sum=T[rt].Val^T[T[rt].To[0]].Sum^T[T[rt].To[1]].Sum;
}
void LCT::PushDown(int rt){
    if(T[rt].Rev){
        if(T[rt].To[0]){
            T[T[rt].To[0]].Rever();
        }   
        if(T[rt].To[1]){
            T[T[rt].To[1]].Rever();
        }
        T[rt].Rev=0;
    }
}
/*--------------- Train -----------------*/
#define catch(rt) (T[T[rt].Fro].To[1]==rt)

void LCT::Rotate(int rt){
    int F=T[rt].Fro;
    int Ff=T[F].Fro;
    int opt=catch(rt);
    if(!IsRoot(F)){
        T[Ff].To[catch(F)]=rt;
    }
    T[F].To[opt]=T[rt].To[!opt];
    T[T[rt].To[!opt]].Fro=F;
    T[rt].To[!opt]=F;
    T[F].Fro=rt;
    T[rt].Fro=Ff;
    PushUp(F);
    PushUp(rt);
}
void LCT::Splay(int rt){
    Update(rt);
    for(int F;F=T[rt].Fro,!IsRoot(rt);Rotate(rt)){
        if(!IsRoot(F)){
            Rotate(catch(F)==catch(rt)?F:rt);
        }
    }
}
bool LCT::IsRoot(int rt){
    return T[T[rt].Fro].To[0]!=rt&&T[T[rt].Fro].To[1]!=rt;
}
int LCT::Access(int rt){
    int P;
    for(P=0;rt;P=rt,rt=T[rt].Fro){
        Splay(rt);
        T[rt].To[1]=P;
        PushUp(rt);
    }
    return P;
}
void LCT::Update(int rt){
    if(!IsRoot(rt)){/////////////////////
        Update(T[rt].Fro);
    }
    PushDown(rt);
}
void LCT::TurnRoot(int rt){
    rt=Access(rt);
    Splay(rt);
    T[rt].Rever();
}
void LCT::Link(int x,int y){
    TurnRoot(x);
    // Splay(x);
    T[x].Fro=y;
}
void LCT::Cut(int x,int y){
    TurnRoot(x);
    Access(y);
    Splay(y);
    T[y].To[0]=T[x].Fro=0;
    PushUp(y);
}
int LCT::Find(int x){
    Access(x);
    Splay(x);
    // PushDown(x);
    while(T[x].To[0]){
        x=T[x].To[0];
        PushDown(x);
    }
    // Splay(x);
    return x;
}
void LCT::Fix(int kl,int val)
{
    T[kl].Val=val;
    // Splay(kl);
}
int LCT::query(int kl){
    return T[kl].Sum;
}
void LCT::Split(int x,int y){
    TurnRoot(x);
    Access(y);
    Splay(y);
}
/*-------------------solution-------------------*/
LCT L;
int n,Q;
void solve(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    cin>>n>>Q;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        L.Fix(i,x);
    }
    for(int i=1;i<=Q;i++){
        int opt,x,y;
        cin>>opt>>x>>y;
        switch(opt){
            case 0:
                L.Split(x,y);
                cout<<L.query(y)<<'\n';
            break;
            case 1:
                if(L.Find(x)!=L.Find(y)){
                    L.Link(x,y);
                }
            break;
            case 2:
                if(L.Find(x)==L.Find(y)){
                    L.Cut(x,y);
                }
            break;
            case 3:
                L.Fix(x,y);
                L.Splay(x);
            break;   
        }
    }
}
2024/1/10 18:42
加载中...