zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Scrapy 概览笔记
    Python 依赖版本控制 (requirements.txt 文件生成和使用)
    Python 虚拟空间的使用
    macOS 所有版本 JDK 安装指南 (with Homebrew)
    鉴权那些事
    Java 位运算符和 int 类型的实现
    ASP.NET Core 入门教程 5、ASP.NET Core MVC 视图传值入门
    如何做好一次知识或技术分享
    ASP.NET Core 入门教程 4、ASP.NET Core MVC控制器入门
    ASP.NET Core 入门教程 3、ASP.NET Core MVC路由入门
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6545218.html
Copyright © 2011-2022 走看看