[国家集训队] Tree2 题解

加边删边 \(LCT\),标记下放同 \(luogu\) 线段树 \(2\) 一题。

时间复杂度 \(O(n\log n)\),第一次交的时候我维护 \(sum\) 不维护 \(sz\ WA\) 完了。

#include<bits/stdc++.h>
#define int long long
#define fa(x) lct[x].fa
#define fl(x) lct[x].fl
#define ad(x) lct[x].ad
#define tm(x) lct[x].tm
#define id(x) lct[x].id
#define sz(x) lct[x].sz
#define val(x) lct[x].val
#define sum(x) lct[x].sum
#define sn(x,i) lct[x].sn[i]
#define inf 1000000000
using namespace std;
const int N=100005,p=51061;
struct node{
    int sn[2],fa,fl,ad,tm,val,sum,id,sz;
}lct[N];int n,m,tp,st[N];
int check(int x){
    return sn(fa(x),0)!=x&&sn(fa(x),1)!=x;
}int chksn(int x){
    return sn(fa(x),1)==x;
}void push_up(int x){
    sum(x)=(sum(sn(x,0))+sum(sn(x,1))+val(x))%p;
    sz(x)=(sz(sn(x,0))+sz(sn(x,1))+1)%p;
}void down(int x,int a,int t){
    if(!x) return;
    val(x)=(val(x)*t+a)%p;
    sum(x)=(sum(x)*t+a*sz(x))%p;
    ad(x)=(ad(x)*t+a)%p;
    tm(x)=tm(x)*t%p;
}void push_down(int x){
    if(!x) return;
    if(fl(x)){
        fl(sn(x,0))^=1,fl(sn(x,1))^=1;
        swap(sn(x,0),sn(x,1)),fl(x)=0;
    }down(sn(x,0),ad(x),tm(x));
    down(sn(x,1),ad(x),tm(x));
    ad(x)=0,tm(x)=1;
}void rotate(int x){
    int y=fa(x),z=fa(y),k=chksn(x);
    if(!check(y))
        sn(z,chksn(y))=x;
    fa(x)=z,fa(y)=x,fa(sn(x,1-k))=y;
    sn(y,k)=sn(x,1-k),sn(x,1-k)=y;
    push_up(y);
}void splay(int x){
    st[tp=1]=x;
    for(int i=x;!check(i);i=fa(i)) st[++tp]=fa(i);
    while(tp) push_down(st[tp--]);
    while(!check(x)){
        int y=fa(x),z=fa(y);
        if(!check(y))
            rotate(chksn(x)!=chksn(y)?x:y);
        rotate(x);
    }push_up(x);
}void access(int x){
    for(int i=0;x;i=x,x=fa(x))
        splay(x),sn(x,1)=i,push_up(x);
}void mk(int x){
    access(x),splay(x),fl(x)^=1;
}void split(int x,int y){
    mk(x),access(y),splay(y);
}void cut(int x,int y){
    split(x,y),sn(y,0)=fa(x)=0;
}void link(int x,int y){
    mk(x),access(y),fa(x)=y;
}signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++) sum(i)=val(i)=sz(i)=tm(i)=1;
    for(int i=1,x,y;i<n;i++) cin>>x>>y,link(x,y);
    while(m--){
        char opt;int x,y,z,w;cin>>opt>>x>>y;
        if(opt=='+')
            cin>>z,split(x,y),down(y,z,1);
        if(opt=='-')
            cin>>z>>w,cut(x,y),link(z,w);
        if(opt=='*')
            cin>>z,split(x,y),down(y,0,z);
        if(opt=='/')
            split(x,y),cout<<sum(y)<<"\n";
    }return 0;
}
posted @   长安一片月_22  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示