zoukankan      html  css  js  c++  java
  • 树链剖分 https://www.luogu.com.cn/problem/P3384

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstdlib>
    #include <vector>
    #include <iostream>
    #define lson rt<<1
    #define rson rt<<1|1
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int N,M,R,P;
    int deep[maxn],F[maxn],size_[maxn],son[maxn];//深度,父亲节点,子树大小,重儿子
    vector<int> G[maxn];
    void dfs1(int x,int f)
    {
        int son_zhong=0,son_num=0;
        size_[x]=1;
        for(int i=0;i<G[x].size();i++)
        {
            int v=G[x][i];
            if(v==f)
                continue;
            F[v]=x;
            deep[v]=deep[x]+1;
            dfs1(v, x);
            size_[x]+=size_[v];
            if(son_num<size_[v])
            {
                son_num=size_[v];
                son_zhong=v;
            }
        }
        son[x]=son_zhong;
    }
    int id[maxn],id_inv[maxn],wt[maxn],w[maxn],top[maxn];
    int cnt;
    void dfs2(int x,int topt)
    {
        id[x]=++cnt;
        top[id[x]]=topt;
        wt[id[x]]=w[x];
        if(son[x]!=0)
            dfs2(son[x], topt);
        for(int i=0;i<G[x].size();i++)
        {
            int v=G[x][i];
            if(v==F[x]||v==son[x])
                continue;
            dfs2(v, v);
        }
    }
    //区间查询 区间更新线段树
    
    ll tree[maxn<<2],lazy[maxn<<2];
    void pushdown(int rt,int l,int r){
        
        lazy[lson]=(lazy[lson]+lazy[rt])%P;
        lazy[rson]=(lazy[rson]+lazy[rt])%P;
        int mid=(l+r)/2;
        tree[lson]=(tree[lson]+lazy[rt]*(mid-l+1))%P;
        tree[rson]=(tree[rson]+lazy[rt]*(r-mid))%P;
        lazy[rt]=0;
    }
    void pushup(int rt)
    {
        tree[rt]=(tree[lson]+tree[rson])%P;
    }
    void build(int rt,int l,int r)
    {
        if(l==r)
        {
            tree[rt]=wt[l];
            return;
        }
        int mid=(l+r)/2;
        build(lson,l,mid);
        build(rson,mid+1,r);
        pushup(rt);
    }
    
    void update(int x,int L,int R,int l,int r,int rt)
    {
        pushdown(rt, l, r);
        if(L<=l&&r<=R)
        {
            tree[rt]=(tree[rt]+(r-l+1)*x);
            lazy[rt]=(x)%P;
            return;
        }
        int mid=(l+r)/2;
        if(mid>=L)
            update(x, L, R, l,mid,lson);
        if(mid<R)
            update(x, L, R, mid+1,r,rson);
        
        pushup(rt);
    }
    ll query(int L,int R,int l,int r,int rt)
    {
        pushdown(rt,l,r);
        if(L<=l&&r<=R)
        {
            return tree[rt];
        }
        int mid=(r+l)/2;
        ll ans=0;
        if(mid>=L)
            ans=(ans+query(L, R, l,mid,lson))%P;
        if(mid<R)
            ans=(ans+query(L, R, mid+1,r,rson))%P;
        return ans;
    }
    int main()
    {
        cin>>N>>M>>R>>P;
        for(int i=1;i<=N;i++)
            cin>>w[i];
        for(int i=0;i<N-1;i++)
        {
            int u,v;
            cin>>u>>v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs1(R, R);
        
        dfs2(R, R);
        for(int i=1;i<=N;i++)
            id_inv[id[i]]=i;
        
        build(1, 1, N);
        
        for(int i=0;i<M;i++)
        {
            int flag;
            cin>>flag;
            if(flag==1)
            {
                int x,y,z;
                cin>>x>>y>>z;
                x=id[x];
                y=id[y];
                while(1)
                {
                    if(deep[top[x]]<deep[top[y]])
                        swap(x, y);
                    
                    if(top[x]==top[y])
                    {
                        if(x<y)
                            swap(x, y);
                        update(z, y, x, 1, N, 1);
                        break;
                    }
                    else
                    {
                        
                        update(z, id[top[x]], x, 1, N, 1);
                        x=id[F[top[x]]];
                    }
                }
            }
            else if(flag==2)
            {
                int x,y;
                cin>>x>>y;
                x=id[x];
                y=id[y];
                ll ans=0;
                while(1)
                {
                    if(deep[top[x]]<deep[top[y]])
                        swap(x, y);
                    
                    if(top[x]==top[y])
                    {
                        if(x<y)
                            swap(x, y);
                        ans=(ans+query( y, x, 1, N, 1))%P;
                        break;
                    }
                    else
                    {
                        ans=(ans+query(id[top[x]], x, 1, N, 1))%P;
                        x=id[F[top[x]]];
                    }
                }
                cout<<ans<<endl;
            }
            else if(flag==3)
            {
                int x,z;
                cin>>x>>z;
                update(z, id[x], id[x]+size_[x]-1, 1, N, 1);
            }
            else if(flag==4)
            {
                int x;
                cin>>x;
                cout<<query(id[x], id[x]+size_[x]-1, 1, N, 1)<<endl;
            }
        }
    }
  • 相关阅读:
    Dapper ORM 用法—Net下无敌的ORM(转)
    微軟将从 .NET 4 以后的版本弃用 System.Data.OracleClient 以及Oracle 的各种连接方法
    最火的.NET开源项目
    sql日期格式化
    项目失败总结
    C#,往线程里传参数的方法总结
    线程的几种用法
    小程序api-01-abcdefg
    cnpm
    关于mpvue和wafer2-client-sdk的 微信登录失败,请检查网络状态
  • 原文地址:https://www.cnblogs.com/King-of-Dark/p/12272926.html
Copyright © 2011-2022 走看看