• 树链刨分(class版)


    class版树链剖(刨)

    感谢沙华大佬的赞助

    其实没什么太大变化,就是用了几次一顿乱指。。。

    CODE:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
     
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define mid ((l+r)>>1)
    #define pushup(rt) t[rt].data=(t[ls].data+t[rs].data)%mod
    #define N 100005
    
    using namespace std;
    
    int n,m,mod,tot,res;
    int top[N],cnt,w[N],wt[N],head[N];
    int fa[N],deep[N],idx[N],son[N],size[N];
    
    class subdivision {
        private:
            struct edge {
                int next,to;
            }e[(N<<1)];
        private:
            struct segtree {
                int data,left,right,tag;
                inline int len() { return right - left + 1; } 
            }t[(N<<2)];
        public:
            inline void edge_build(int u,int v) {
                e[++tot].to = v;
                e[tot].next = head[u];
                head[u] = tot;
                return ;
            }
        public:
            inline void tree_build(int rt , int l , int r){
                t[rt].left = l; 
    			t[rt].right = r;
    			t[rt].tag = 0;
                if(l == r) {
                    t[rt].data = wt[l];
                    return ;
                }
                tree_build(ls,l,mid);
    			tree_build(rs,mid +1,r);
                pushup(rt);
    			return ; 
            }
        private:
            inline void pushdown(int rt) {
                t[ls].tag = (t[ls].tag + t[rt].tag) % mod;
                t[rs].tag = (t[rs].tag + t[rt].tag) % mod;
                t[ls].data = (t[ls].data + t[rt].tag * t[ls].len() ) % mod;
                t[rs].data = (t[rs].data + t[rt].tag * t[rs].len() ) % mod;
                t[rt].tag = 0;
    			return ; 
            }
        public:
            inline void update(int rt , int ll , int rr , int w) {
                int l = t[rt].left;
    			int r = t[rt].right;
                if(ll <= l && r <= rr) {
                    t[rt].tag += w;
                    t[rt].data = (t[rt].data + t[rt].len() * w) % mod;
                    return ; 
                }
                if(t[rt].tag) pushdown(rt);
                if(ll <= mid) update(ls,ll,rr,w);
                if(rr > mid) update(rs,ll,rr,w);
                pushup(rt);
    			return ; 
            }
        public:
            inline void query(int rt,int ll,int rr) {
                int l = t[rt].left;
    			int r = t[rt].right;
                if(ll <= l && r <= rr) {
                    res += t[rt].data;
                    return ;
                }
                if(t[rt].tag) pushdown(rt);
                if(ll <= mid) query(ls,ll,rr);
                if(rr > mid) query(rs,ll,rr);
                return ;
            }
        public:
            inline void dfs1(int now,int f,int dep) {
                deep[now] = dep;
    			fa[now] = f;
    			size[now] = 1;
    			int maxson = -1;
                for(int i = head[now] ; i ; i = e[i].next) {
                    int y = e[i].to;
    				if(y == f) continue;
                    dfs1(y , now , dep + 1);
    				size[now] += size[y];
                    if(size[y] > maxson) {
                        son[now] = y; 
    					maxson = size[y];
                    }
                }
                return ;
            }
        public:
            inline void dfs2(int now,int topf) {
                idx[now] = ++cnt;
    			wt[cnt] = w[now];
    			top[now] = topf;
                if(!son[now]) return ;
    			dfs2(son[now],topf);
                for(int i = head[now] ; i ; i = e[i].next) {
                    int y = e[i].to;
                    if(y == fa[now] || y == son[now]) continue;
                    dfs2(y,y);
                }
                return ;
            }
        public:
            inline int qrange(int x,int y) {
                int ans = 0;
                while(top[x] != top[y]) {
                    if(deep[top[x]] < deep[top[y]]) swap(x,y);
                    res = 0;
    				query(1 , idx[top[x]] , idx[x]);
                    ans = (ans + res) % mod;
    				x = fa[top[x]];
                }
                if(deep[x] > deep[y]) swap(x,y);
                res = 0;
    			query(1 , idx[x] , idx[y]);
                return (ans + res) % mod;
            }
        public:
            inline void uprange(int x,int y,int k) {
                k %= mod;
                while(top[x] != top[y]) {
                    if(deep[top[x]] < deep[top[y]]) swap(x,y);
                    update(1 , idx[top[x]] , idx[x],k);
                    x = fa[top[x]];
                }
                if(deep[x] > deep[y]) swap(x,y);
                update(1 , idx[x] , idx[y] , k);
                return ;
            }
    };
    
    subdivision *s;
    
    int main(){
        int root,a,b;
        scanf("%d%d%d%d",&n,&m,&root,&mod);
        for(int i = 1 ; i <= n ; ++i) 
            scanf("%d",&w[i]);
        for(int i = 1 ; i < n ; ++i){
            scanf("%d%d",&a,&b);
            s->edge_build(a,b);
            s->edge_build(b,a);
        }
        s->dfs1(root,0,1);
        s->dfs2(root,root);
        s->tree_build(1,1,n);
        int k,x,y,z;
        while(m--) {
            scanf("%d%d",&k,&x);
            if(k == 1) {
                scanf("%d%d",&y,&z);
                s->uprange(x,y,z);
            }
            if(k == 2) {
                scanf("%d",&y);
                printf("%d
    ",s->qrange(x,y) );
            }
            if(k == 3) {
                scanf("%d",&z);
                s->update(1 , idx[x] , idx[x] + size[x]-1,z);
            }
            if(k == 4) {
                res = 0;
                s->query(1 , idx[x] , idx[x] + size[x]-1);
                printf("%d
    ",res % mod);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    C#中的赋值运算符及其运算规则
    值类型与引用类型
    变量的作用域和生存周期
    Eclipse 和 Vim 协同使用使用Eclim插件开发Python程序
    使用合适的设计模式一步步优化前端代码
    Vue.js 服务端渲染业务入门实践
    翻译连载 | 第 9 章:递归(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
    翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数式编程》 第 7 章: 闭包 vs 对象
    翻译连载 | 第 10 章:异步的函数式(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
    微信小程序教学第四章第二节(含视频):小程序中级实战教程:详情视图渲染
  • 原文地址:https://www.cnblogs.com/Repulser/p/9715807.html
Copyright © 2020-2023  润新知