• bzoj 2631: tree link-cut-tree


    题目:

    Description

    一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
    + u v c:将u到v的路径上的点的权值都加上自然数c;
    - u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
    * u v c:将u到v的路径上的点的权值都乘上自然数c;
    / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

    Input

    第一行两个整数n,q
    接下来n-1行每行两个正整数u,v,描述这棵树
    接下来q行,每行描述一个操作
    Output
    对于每个/对应的答案输出一行

    题解

    模板题
    用了15mins打完,调了半小时

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(ll &x){
        x=0;char ch;bool flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const ll mod = 51061;
    const ll maxn = 210010;
    struct Node{
        Node *ch[2],*fa;
        ll mul,add,w,sum,tag;
        ll siz;
        void update();
        void pushdown();
        void set();
    }*null;
    Node mem[maxn],*it;
    inline void init(){
        it = mem;null = it++;
        null->ch[0] = null->ch[1] = null->fa = null;
        null->mul = null->add = null->w = null->sum = 0;
        null->tag = null->siz = 0;
    }
    inline Node* newNode(ll w){
        Node *p = it++;p->ch[0] = p->ch[1] = p->fa = null;
        p->mul = 1;p->siz = 1;
        p->add = p->tag = 0;p->w = p->sum = w;return p;
    }
    inline void Node::update(){
        if(this == null) return;
        sum = (ch[0]->sum + ch[1]->sum + w) % mod;
        siz = (ch[0]->siz + ch[1]->siz + 1);
    }
    inline void Node::pushdown(){
        if(this == null) return;
        if(mul != 1){
            if(ch[0] != null){
                ch[0]->add = ch[0]->add*mul % mod;
                ch[0]->mul = ch[0]->mul*mul % mod;
                ch[0]->w = ch[0]->w*mul % mod;
                ch[0]->sum = ch[0]->sum*mul % mod;
            }
            if(ch[1] != null){
                ch[1]->add = ch[1]->add*mul % mod;
                ch[1]->mul = ch[1]->mul*mul % mod;
                ch[1]->w = ch[1]->w*mul % mod;
                ch[1]->sum = ch[1]->sum*mul % mod;
            }
            mul = 1;
        }
        if(add != 0){
            if(ch[0] != null){
                ch[0]->add = (ch[0]->add + add) % mod;
                ch[0]->sum = (ch[0]->sum + add*ch[0]->siz) % mod;
                ch[0]->w = (ch[0]->w + add) % mod;
            }
            if(ch[1] != null){
                ch[1]->add = (ch[1]->add + add) % mod;
                ch[1]->sum = (ch[1]->sum + add*ch[1]->siz) % mod;
                ch[1]->w = (ch[1]->w + add) % mod;
            }
            add = 0;
        }
        if(tag != 0){
            if(ch[0] != null) ch[0]->tag ^= 1;
            if(ch[1] != null) ch[1]->tag ^= 1;
            swap(ch[0],ch[1]);tag = 0;
        }
    }
    inline void rotate(Node *p,Node *x){
        ll k = p == x->ch[1];
        Node *y = p->ch[k^1],*z = x->fa;
        if(z->ch[0] == x) z->ch[0] = p;
        if(z->ch[1] == x) z->ch[1] = p;
        if(y != null) y->fa = x;
        p->fa = z;p->ch[k^1] = x;
        x->fa = p;x->ch[k] = y;
        x->update();p->update(); 
    }
    inline bool isroot(Node *p){
        return (p == null) || (p->fa->ch[0] != p && p->fa->ch[1] != p);
    }
    inline void Splay(Node *p){
        p->pushdown();
        while(!isroot(p)){
            Node *x = p->fa,*y = x->fa;
            y->pushdown();x->pushdown();p->pushdown();
            if(isroot(x)) rotate(p,x);
            else if((p == x->ch[0])^(x == y->ch[0])) rotate(p,x),rotate(p,y);
            else rotate(x,y),rotate(p,x);
        }p->update();
    }
    inline Node* Access(Node *x){
        for(Node *y = null;x != null;y = x,x = x->fa)
            Splay(x),x->ch[1] = y,x->update();
        return x;
    }
    inline void makeRoot(Node *x){
        Access(x);Splay(x);x->tag ^= 1;
    }
    inline void link(Node *x,Node *y){
        makeRoot(x);x->fa = y;
    }
    inline void cut(Node *x,Node *y){
        makeRoot(x);Access(y);Splay(y);
        y->ch[0] = y->ch[0]->fa = null;
        y->update();
    }
    inline void inc(Node *x,Node *y,ll w){
        makeRoot(x);Access(y);Splay(y);
        y->add += w;y->add %= mod;
        y->sum += w*y->siz;
        y->sum %= mod;
        y->w += w;y->w %= mod;
    }
    inline void mul(Node *x,Node *y,ll w){
        makeRoot(x);Access(y);Splay(y);
        y->add *= w;y->add %= mod;
        y->mul *= w;y->mul %= mod;
        y->sum *= w;y->sum %= mod;
        y->w *= w;y->w %= mod;
    }
    inline ll query(Node *x,Node *y){
        makeRoot(x);Access(y);Splay(y);
        return y->sum;
    }
    int main(){
        init();
        ll n,q;read(n);read(q);
        for(ll i=1;i<=n;++i) newNode(1);
        for(ll i=1,u,v;i<n;++i){
            read(u);read(v);
            link(mem+u,mem+v);
        }
        char ch;
        ll u,v,x;
        while(q--){
            while(ch = getchar(),ch<'!');
            if(ch == '+'){
                read(u);read(v);read(x);
                inc(mem+u,mem+v,x);
            }else if(ch == '-'){
                read(u);read(v);
                cut(mem+u,mem+v);
                read(u);read(v);
                link(mem+u,mem+v);
            }else if(ch == '*'){
                read(u);read(v);read(x);
                mul(mem+u,mem+v,x);
            }else if(ch == '/'){
                read(u);read(v);
                printf("%lld
    ",query(mem+u,mem+v));
            }
        }
        getchar();getchar();
        return 0;
    }
    
  • 相关阅读:
    C#演练—Windows应用程序—在windows窗体上动态创建上下文菜单
    C#演练—Windows应用程序—可视化继承
    C#演练—Windows应用程序—创建主从windows窗体
    小胖IT大讲堂之三 Hook实战(二) SQL Monitor山寨版
    小胖的2011总结之回忆篇
    Oracle安装示例数据库
    《领域驱动设计》读书笔记(一) 分离领域
    小胖IT大讲堂之一 .NET Reflector工具介绍
    10年前我不是小胖,也是个“诗人”
    忘记
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6545218.html
Copyright © 2020-2023  润新知