树链刨分(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\n",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\n",res % mod);
        }
    }
    return 0;
}
posted @ 2018-09-27 21:39  西窗夜雨  阅读(237)  评论(2编辑  收藏  举报