Top Tree 模板

Sone1,AAAT。

#include <iostream>
#include <vector>
#include <cassert>
#define UP(i,s,e) for(auto i=s; i<e; ++i)
using std::cin; using std::cout;
constexpr int N = 1e5, M = 1e5;
namespace TopTree{ // }{{{
struct Modify_tag{
    int val; bool ismodi;
    Modify_tag(){}
    Modify_tag(int v, bool t):val(v), ismodi(t){}
    bool is_identity(){ return !val && !ismodi; }
    Modify_tag &operator>>=(Modify_tag b){
        if(b.ismodi) *this = b;
        else val += b.val;
        return *this;
    }
};
struct Info{
    int mn, mx, sum;
    int siz;
    bool is_identity(){ return siz == 0; }
    Info(){}
    Info(int x):mn(x), mx(x), sum(x), siz(1){}
    Info &apply(Modify_tag mo){
        if(!mo.val && !mo.ismodi) return *this;
        if(siz == 0) return *this;
        if(mo.ismodi){
            mn = mx = sum = mo.val;
            sum *= siz;
        } else {
            mn += mo.val; mx += mo.val;
            sum += mo.val * siz;
        }
        return *this;
    }
};
using NT = enum { RAKE, COMPRESS };
struct Node{
    Node *fa;
    Node *ls, *ms, *rs;
    NT typ;
    int val;
    Info hinfo, linfo; // light not includes heavy
    Modify_tag hmodi, lmodi;
    bool rev;
    Node &addlmodi(Modify_tag);
    Node &addhmodi(Modify_tag);
} nil_, *const nil = &nil_, nds[N*2];
int nodcnt = 0;
std::vector<int> rubbish;
Node &Node::addlmodi(Modify_tag lm){lmodi >>= lm; return *this; }
Node &Node::addhmodi(Modify_tag hm){hmodi >>= hm; return *this; }
Node *nnod(){
    if(rubbish.empty()) return nds+nodcnt++;
    Node *p = nds + rubbish.back();
    rubbish.pop_back();
    return p;
}
Node *mknode(){ Node *p = nnod(); p->hmodi = p->lmodi = Modify_tag(0, 0); return p;}
void erase(Node *x){ rubbish.push_back(x-nds); }
void flip(Node *x){ if(x != nil) x->rev ^= 1; }
void pushrev(Node *x){ 
    if(x == nil || x->typ == RAKE) return;
    if(!x->rev) return;
    std::swap(x->ls, x->rs);
    x->rev ^= 1;
    flip(x->ls);
    flip(x->rs);
}
Info operator+(Info a, Info b){
    if(a.is_identity() || b.is_identity()) return a.is_identity() ? b : a;
    Info ret;
    ret.mn = std::min(a.mn, b.mn);
    ret.mx = std::max(a.mx, b.mx);
    ret.sum = a.sum + b.sum;
    ret.siz = a.siz + b.siz;
    return ret;
}
void pushup(Node *x){
    if(x == nil) return;
    pushrev(x);
    if(x->typ == RAKE){
        x->linfo = (x->ls->linfo + x->ms->hinfo + x->ms->linfo + x->rs->linfo).apply(x->lmodi);
    } else {
        x->hinfo = (x->ls->hinfo + x->rs->hinfo + Info(x->val)).apply(x->hmodi);
        x->linfo = (x->ls->linfo + x->ms->linfo + x->rs->linfo).apply(x->lmodi);
    }
}
void pushdown(Node *x){ 
    pushrev(x); 
    for(auto son:{x->ls, x->rs}){
        if(son == nil) continue;
        son->addlmodi(x->lmodi);
        if(x->typ == COMPRESS) son->addhmodi(x->hmodi);
        pushup(son);
    }
    if(x->ms != nil){
        x->ms->addlmodi(x->lmodi);
        if(x->typ == RAKE) x->ms->addhmodi(x->lmodi);
        pushup(x->ms);
    }
    assert(x->typ != RAKE || x->hmodi.is_identity());
    if(!x->hmodi.is_identity()){
        if(x->hmodi.ismodi){
            x->val = x->hmodi.val;
        } else {
            x->val += x->hmodi.val;
        }
    }
    x->lmodi.val = x->lmodi.ismodi = 0;
    x->hmodi.val = x->hmodi.ismodi = 0;
}
bool nroot(Node *x){ return x == x->fa->ls or x == x->fa->rs; }
bool isrs(Node *x){ return x == x->fa->rs; }
void pushdddd(Node *x){
    if(nroot(x)) pushdddd(x->fa);
    pushdown(x);
}
void setfa(Node *x, Node *f, int which){
    if(x != nil) x->fa = f;
    if(which == 0) f->ls = x;
    else if(which == 1) f->rs = x;
    else f->ms = x;
}
void rotate(Node *x){
    if(x == nil || !nroot(x)) return;
    Node *y = x->fa, *z = y->fa;
    if(z != nil){
        if(z->ls == y) z->ls = x;
        else if(z->ms == y) z->ms = x;
        else if(z->rs == y) z->rs = x;
    }
    if(x == y->ls){
        setfa(x->rs, y, 0);
        x->rs = y;
    } else {
        setfa(x->ls, y, 1);
        x->ls = y;
    }
    y->fa = x; x->fa = z;
    pushup(y);
    pushup(x);
}
void splay(Node *x, Node *to = nil){
    pushdddd(x);
    for(Node *y; y = x->fa, nroot(x) && y!=to; rotate(x)){
        if(y->fa != to && nroot(y)){
            rotate(isrs(x) ^ isrs(y) ? x : y);
        }
    }
}
void unuse(Node *x){
    assert(x->typ == RAKE);
    setfa(x->ms, x->fa, 1);
    x->ms = nil;
    if(x->ls != nil){
        Node *p = x->ls;
        pushdown(p);
        while(p->rs != nil) p = p->rs, pushdown(p);
        splay(p, x);
        setfa(x->rs, p, 1);
        setfa(p, x->fa, 2);
        pushup(p);
        pushup(x->fa);
    } else {
        setfa(x->rs, x->fa, 2);
    }
    erase(x);
}
void splice(Node *x){ 
    assert(x->typ == RAKE);
    splay(x);
    Node *y = x->fa;
    splay(y);
    pushdown(x);
    if(y->rs != nil){
        std::swap(x->ms->fa, y->rs->fa);
        std::swap(x->ms, y->rs);
        pushup(x);
    } else {
        unuse(x);
    }
    pushup(y);
}
void access(Node *x){
    splay(x);
    if(x->rs != nil){
        Node *y = mknode();
        y->val = 0;
        y->rev = 0;
        setfa(x->ms, y, 0);
        setfa(x->rs, y, 2); x->rs = nil;
        setfa(y, x, 2);
        y->rs = nil;
        y->typ = RAKE;
        pushup(y);
        pushup(x);
    }
    Node *p = x;
    while(p->fa != nil){
        splice(p->fa);
        p = p->fa;
        pushup(p);
    }
    splay(x);
}
void mkroot(Node *x){ access(x); flip(x); }
void expose(Node *x, Node *y){ mkroot(x); access(y); }
Node *findrt(Node *x){
    access(x);
    pushdown(x);
    while(x->ls != nil) x = x->ls, pushdown(x);
    splay(x);
    return x;
}
void link(Node *x, Node *y){
    //if(findrt(x) == findrt(y)) return;
    access(x);
    mkroot(y);
    setfa(y, x, 1);
    pushup(x);
}
void cut(Node *x, Node *y){
    expose(x, y);
    if(y->ls != x || x->rs != nil) return;
    x->fa = y->ls = nil;
    pushup(y);
}
} // {}}}
namespace m{ // }{{{
int in, iq;
using TopTree::Node;
Node *ndid[N];
int nowrt;
std::vector<std::pair<int, int>> tre;
void check(){
    UP(i, 0, in){
        for(auto son:{ndid[i]->ls, ndid[i]->ms, ndid[i]->rs}){
            if(son == TopTree::nil) return;
            if(son->fa != ndid[i]) throw 114514;
            if(son == ndid[i]->fa) throw "WTF";
        }
    }
}
void get_graph(Node *p = ndid[0], Node *from = ndid[0]){
    for(Node *x:{p->ls, p->ms, p->rs}){
        if(x == TopTree::nil) continue;
        std::cerr << x-ndid[0] << " " << p-ndid[0] << " " << (x==p->ms ? 2 : TopTree::isrs(x)) << '\t';
        if(x != from) get_graph(x, p);
    }
    if(p->fa != TopTree::nil && from != p->fa) get_graph(p->fa, p);
}
void work(){
    cin >> in >> iq;
    UP(i, 0, in-1){
        int iu, iv; cin >> iu >> iv; iu--, iv--;
        tre.push_back({iu, iv});
    }
    UP(i, 0, in){
        int x; cin >> x;
        Node *p = TopTree::mknode();
        p->ls = p->ms = p->rs = p->fa = TopTree::nil;
        p->val = x;
        p->typ = TopTree::COMPRESS;
        p->rev = false;
        TopTree::pushup(p);
        ndid[i] = p;
    }
    cin >> nowrt; nowrt--;
    for(auto &i:tre){
        TopTree::link(ndid[i.first], ndid[i.second]);
    }
    tre.clear(); tre.shrink_to_fit();
    UP(i, 0, iq){
        int op, x, y, z, ans;
        cin >> op;
        switch(op){
            case 0:
                cin >> x >> y; x--;
                TopTree::expose(ndid[nowrt], ndid[x]);
                if(ndid[x]->ms != TopTree::nil){
                    ndid[x]->ms->addlmodi(TopTree::Modify_tag(y, 1));
                    TopTree::pushup(ndid[x]->ms);
                }
                ndid[x]->val = y;
                TopTree::pushup(ndid[x]);
                break;
            case 1:
                cin >> x; x--;
                nowrt = x;
                break;
            case 2:
                cin >> x >> y >> z; x--, y--;
                TopTree::expose(ndid[x], ndid[y]);
                ndid[y]->addhmodi(TopTree::Modify_tag(z, 1));
                TopTree::pushup(ndid[y]);
                break;
            case 3:
                cin >> x; x--;
                TopTree::expose(ndid[nowrt], ndid[x]);
                ans = ndid[x]->val;
                if(ndid[x]->ms != TopTree::nil){
                    ans = std::min(ans, ndid[x]->ms->linfo.mn);
                }
                cout << ans << '\n';
                break;
            case 4:
                cin >> x; x--;
                TopTree::expose(ndid[nowrt], ndid[x]);
                ans = ndid[x]->val;
                if(ndid[x]->ms != TopTree::nil){
                    ans = std::max(ans, ndid[x]->ms->linfo.mx);
                }
                cout << ans << '\n';
                break;
            case 5:
                cin >> x >> y; x--;
                TopTree::expose(ndid[nowrt], ndid[x]);
                ndid[x]->val += y;
                if(ndid[x]->ms != TopTree::nil){
                    ndid[x]->ms->addlmodi(TopTree::Modify_tag(y, 0));
                    TopTree::pushup(ndid[x]->ms);
                }
                TopTree::pushup(ndid[x]);
                break;
            case 6:
                cin >> x >> y >> z; x--, y--;
                TopTree::expose(ndid[x], ndid[y]);
                ndid[y]->addhmodi(TopTree::Modify_tag(z, 0));
                TopTree::pushup(ndid[y]);
                break;
            case 7:
                cin >> x >> y; x--, y--;
                TopTree::expose(ndid[x], ndid[y]);
                cout << ndid[y]->hinfo.mn << '\n';
                break;
            case 8:
                cin >> x >> y; x--, y--;
                TopTree::expose(ndid[x], ndid[y]);
                cout << ndid[y]->hinfo.mx << '\n';
                break;
            case 9:
                cin >> x >> y; x--, y--;
                if(x == y) break;
                TopTree::expose(ndid[nowrt], ndid[x]);
                if(1){
                    TopTree::pushrev(ndid[x]);
                    Node *p = ndid[x]->ls;
                    if(p == TopTree::nil) break;
                    for(; TopTree::pushrev(p), p->rs != TopTree::nil; p = p->rs){;}
                    TopTree::cut(ndid[x], p);
                    if(TopTree::findrt(ndid[x]) == TopTree::findrt(ndid[y])){
                        TopTree::link(ndid[x], p);
                    } else {
                        TopTree::link(ndid[x], ndid[y]);
                    }
                }
                break;
            case 10:
                cin >> x >> y; x--, y--;
                TopTree::expose(ndid[x], ndid[y]);
                cout << ndid[y]->hinfo.sum << '\n';
                break;
            case 11:
                cin >> x; x--;
                TopTree::expose(ndid[nowrt], ndid[x]);
                ans = ndid[x]->val;
                if(ndid[x]->ms != TopTree::nil) ans += ndid[x]->ms->linfo.sum;
                cout << ans << '\n';
            default:;
        }
    }
}
} // {}}}
int main(){std::ios::sync_with_stdio(0); cin.tie(0); m::work(); return 0;}
posted @ 2023-12-03 15:25  383494  阅读(71)  评论(0编辑  收藏  举报