zoukankan      html  css  js  c++  java
  • [模板]树链剖分

    #include<bits/stdc++.h>
    #define lson(x) (x << 1)
    #define rson(x) (x << 1 | 1)
    using namespace std;
    
    const int N = 100010,M = 200010;
    int n,m,r,p;
    long long a[N];
    int d[N],son[N],fa[N],siz[N],top[N],rk[N],id[N],cnt;//树链剖分 
    int head[N],edge[M],nxt[M],from[M],to[M],tot;//邻接表 
    void add_edge(int x,int y){
        from[++tot] = x;
        to[tot] = y;
        nxt[tot] = head[x];
        head[x] = tot;
    }
    
    //线段树
    struct Tree{
        int l,r;
        long long sum,tag;  
    }t[N*4];
    void push_up(int x) { t[x].sum = (t[lson(x)].sum + t[rson(x)].sum) % p; }
    void push_down(int x){
        if(t[x].tag){
            t[lson(x)].tag = (t[lson(x)].tag + t[x].tag) % p; 
            t[lson(x)].sum = (t[lson(x)].sum + t[x].tag *(t[lson(x)].r - t[lson(x)].l + 1)) % p;
            t[rson(x)].tag = (t[rson(x)].tag + t[x].tag) % p; 
            t[rson(x)].sum = (t[rson(x)].sum + t[x].tag *(t[rson(x)].r - t[rson(x)].l + 1)) % p;
            t[x].tag = 0;
        }
    }
    void build(int x,int ll,int rr){
        t[x].l = ll; t[x].r = rr;
        if(ll == rr) { 
            t[x].sum = a[rk[ll]]; 
            if(t[x].sum > p) t[x].sum %= p; 
            return; 
        }
        int mid = (ll + rr) >> 1;
        build(lson(x),ll,mid);
        build(rson(x),mid + 1,rr);
        push_up(x);
    }
    void update(int x,int ll,int rr,int k){
        if(ll <= t[x].l && t[x].r <= rr){
            t[x].sum = (t[x].sum + k * (t[x].r - t[x].l + 1)) % p;
            t[x].tag = (t[x].tag + k) % p;
            return;
        }
        push_down(x);
        int mid = (t[x].l + t[x].r) >> 1;
        if(ll <= mid) update(lson(x),ll,rr,k);
        if(mid < rr)  update(rson(x),ll,rr,k);
        push_up(x);
    }
    long long query(int x,int ll,int rr){
        if(ll <= t[x].l && t[x].r <= rr) return t[x].sum;
        int mid = (t[x].l + t[x].r) >> 1;
        long long res = 0;
        push_down(x);
        if(ll <= mid) res = (res + query(lson(x),ll,rr)) % p;
        if(mid < rr)  res = (res + query(rson(x),ll,rr)) % p;
        push_up(x);
        return res;
    }
    
    //树链剖分 
    void dfs1(int x){
        siz[x] = 1;
        for(int i = head[x]; i; i = nxt[i])
            if(!siz[to[i]]){
                d[to[i]] = d[x] + 1;
                fa[to[i]] = x;
                dfs1(to[i]);
                siz[x] +=  siz[to[i]];
                if(!son[x] || siz[to[i]] > siz[son[x]])
                    son[x] = to[i];
            }
    }
    void dfs2(int x,int t){
        top[x] = t;
        id[x] = ++cnt;
        rk[cnt] = x;
        if(!son[x]) return;
        dfs2(son[x],t);
        for(int i = head[x]; i; i = nxt[i])
            if(to[i] != son[x] && to[i] != fa[x])
                dfs2(to[i],to[i]);
    }
    int main(){
    //    freopen("testdata (6).in","r",stdin);
    //    freopen("test.txt","w",stdout);
        cin >> n >> m >> r >> p;
        for(int i = 1; i <= n; i++)
            scanf("%lld",&a[i]);
        for(int i = 1; i < n; i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add_edge(x,y);
            add_edge(y,x);
        }
        dfs1(r);
        dfs2(r,r);
        build(1,1,n);
        for(int i = 1; i <= m; i++){
            int op = 0,x = 0,y = 0,z = 0;
            scanf("%d%d",&op,&x);
            if(op == 1){
                scanf("%d%d",&y,&z);
                while(top[x] != top[y]){
                    if(d[top[y]] > d[top[x]]) swap(x,y);
                    update(1,id[top[x]],id[x],z);
                    x = fa[top[x]];
                }
                if(d[x] > d[y]) swap(x,y);
                    update(1,id[x],id[y],z);
            }
            if(op == 2){
                scanf("%d",&y);
                long long ans = 0;
                while(top[x] != top[y]){
                    if(d[top[y]] > d[top[x]]) swap(x,y);
                    ans = (ans + query(1,id[top[x]],id[x])) % p;
                    x = fa[top[x]];
                }
                if(d[x] > d[y]) swap(x,y);
                ans = (ans + query(1,id[x],id[y]))% p;
                printf("%lld
    ",ans);
            }
            if(op == 3){
                scanf("%d",&z);
                update(1,id[x],id[x] + siz[x] - 1,z);
            }
            if(op == 4){
                printf("%lld
    ",query(1,id[x],id[x] + siz[x] - 1));
            } 
        }
        return 0;
    }
    
  • 相关阅读:
    关于C++中操作符重载的疑问 :四个运算符=, ->, [], ()不可以重载为全局函数(友员函数)...
    linux内核移植过程问题总结
    关于开发板用tftp下载失败分析
    阿里云ECS下安装的MySQL无法远程连接?
    uva729
    使用 Confluence 6 服务器移动应用
    Confluence 6 移动浏览查看任务
    Confluence 6 移动浏览查看通知
    Confluence 6 移动浏览查看页面,博客和评论
    Confluence 6 移动浏览搜索内容和人
  • 原文地址:https://www.cnblogs.com/FoxC/p/11256624.html
Copyright © 2011-2022 走看看