zoukankan      html  css  js  c++  java
  • 树链剖分

    洛谷模板

    #include<bits/stdc++.h>
    using namespace std;
    const int M=500500;
    struct TREE{int l,r,w,lz;}t[M<<2];
    struct EDGE{int v,next;}e[M];
    int head[M],edget,n,m,r,mod,w[M];
    int deep[M],fa[M],son[M],siz[M];    //节点的深度  节点的父亲  节点的重儿子  节点子树的大小
    int top[M],idn[M],cnt,val[M];       //节点所在重链的头节点  节点新的编号  新编号为i的点的点权
    void add(int,int);                  //加边进入邻接表
    int dfs1(int,int,int);              //求每个节点的深度、重儿子和dfs序
    void dfs2(int,int);                 //对整个树进行重新编号
    void build(int,int,int);            //建树
    void update(int);                   //更新节点值
    void IntervalAdd(int,int,int,int);  //区间加
    int IntervalSum(int,int,int);       //区间求和
    void down(int);                     //下推标记
    void TreeSum(int,int);              //求x到y路径上的和
    void TreeAdd(int,int,int);          //给x到y路径上的每一个点加val权值
    int main(){
        ios::sync_with_stdio(false); 
        register int i;
        int x,y,z;
        char q;
        cin>>n>>m>>r>>mod;
        for(i=1;i<=n;++i) cin>>w[i];
        for(i=1;i<n;++i){
            cin>>x>>y;
            add(x,y);
            add(y,x);
        }
        dfs1(r,0,1);
        dfs2(r,r);
        build(1,n,1);
        for(i=1;i<=m;++i){
            cin>>q;
            switch(q){
                case '1':{cin>>x>>y>>z; TreeAdd(x,y,z); break;}
                case '2':{cin>>x>>y; TreeSum(x,y); break;}
                case '3':{cin>>x>>z; IntervalAdd(1,idn[x],idn[x]+siz[x]-1,z); break;}
                case '4':{cin>>x; printf("%d
    ",IntervalSum(1,idn[x],idn[x]+siz[x]-1)%mod); break;}
            }
        }
        return 0;
    }
    void add(int x,int y){
        e[++edget].v=y;
        e[edget].next=head[x];
        head[x]=edget;
    }
    int dfs1(int x,int f,int dp){
        fa[x]=f;
        deep[x]=dp;
        siz[x]=1;
        int maxsiz=-1;
        for(register int i=head[x];i;i=e[i].next){
            if(e[i].v==f) continue;
            siz[x]+=dfs1(e[i].v,x,dp+1);
            if(siz[e[i].v]>maxsiz){   //修改重儿子
                son[x]=e[i].v;
                maxsiz=siz[e[i].v];
            }
        }
        return siz[x];
    }
    void dfs2(int x,int topx){ //topx表示节点x所在重链的头节点 
        top[x]=topx;
        idn[x]=++cnt;
        val[cnt]=w[x];
        if(!son[x]) return;
        dfs2(son[x],topx);
        for(register int i=head[x];i;i=e[i].next)  if(!idn[e[i].v])   dfs2(e[i].v,e[i].v);
    }
    void build(int l,int r,int u){
        t[u].l=l,t[u].r=r;
        if(l==r){
            t[u].w=val[l];
            return;
        }
        int m=(l+r)>>1;
        build(l,m,u<<1);
        build(m+1,r,u<<1|1);
        update(u);
    }
    void update(int u){
        t[u].w=(t[u<<1].w+t[u<<1|1].w+mod)%mod;
    }
    void IntervalAdd(int u,int l,int r,int val){
        if(t[u].l>=l && t[u].r<=r){
            t[u].w+=(t[u].r-t[u].l+1)*val;
            t[u].lz+=val;
            return;
        }
        if(t[u].lz) down(u);
        int m=(t[u].l+t[u].r)>>1;
        if(m>=l) IntervalAdd(u<<1,l,r,val);
        if(m<r) IntervalAdd(u<<1|1,l,r,val);
        update(u);
    }
    int IntervalSum(int u,int l,int r){
        int ans=0;
        if(t[u].l>=l && t[u].r<=r) return t[u].w;
        if(t[u].lz) down(u);
        int m=(t[u].l+t[u].r)>>1;
        if(m>=l) ans=(ans+IntervalSum(u<<1,l,r))%mod;
        if(m<r) ans=(ans+IntervalSum(u<<1|1,l,r))%mod;
        return ans; 
    }
    void down(int u){
        t[u<<1].lz+=t[u].lz;
        t[u<<1|1].lz+=t[u].lz;
        t[u<<1].w=(t[u<<1].w+(t[u<<1].r-t[u<<1].l+1)*t[u].lz)%mod;
        t[u<<1|1].w=(t[u<<1|1].w+(t[u<<1|1].r-t[u<<1|1].l+1)*t[u].lz)%mod;
        t[u].lz=0;
    }
    void TreeSum(int x,int y){
        int ans=0;
        while(top[x]!=top[y]){ //当x和y不在同一重链上时,先跳到同一条重链上 
            if(deep[top[x]]<deep[top[y]]) swap(x,y); //把深度深的向上跳 
            ans=(ans+IntervalSum(1,idn[top[x]],idn[x]))%mod; //直接跳到fa[top[x]],并记录权值和 
            x=fa[top[x]];
        }
        if(deep[x]>deep[y]) swap(x,y); //线段树的操作区间[l,r]要满足l<=r 
        ans=(ans+IntervalSum(1,idn[x],idn[y]))%mod;
        printf("%d
    ",ans);
    }
    void TreeAdd(int x,int y,int val){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            IntervalAdd(1,idn[top[x]],idn[x],val);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y]) swap(x,y);
        IntervalAdd(1,idn[x],idn[y],val);
    }

     树的统计

    #include<bits/stdc++.h>
    using namespace std;
    const int M=500500;
    struct EDGE{int v,next;}e[M];
    struct TREE{int l,r,w,maxn,lz;}t[M<<2];
    int n,w[M],head[M],num,q,deep[M],cnt;
    int fa[M],top[M],idn[M],siz[M],son[M],val[M];
    string s;
    inline void add(int,int);
    int dfs1(int,int,int);
    inline void dfs2(int,int);
    inline void build(int,int,int);
    inline void update(int);
    int IntervalSum(int,int,int);
    int IntervalMax(int,int,int);
    inline void SinglepointChange(int,int,int);
    inline void TreeSum(int,int);
    inline void TreeMax(int,int);
    int main(){
        ios::sync_with_stdio(0);
        register int i,j;
        int x,y;
        cin>>n;
        for(i=1;i<n;++i){
            cin>>x>>y;
            add(x,y);
            add(y,x);
        }
        for(i=1;i<=n;++i) cin>>w[i];
        dfs1(1,0,1);
        dfs2(1,1);
        build(1,n,1);
        cin>>q;
        for(i=1;i<=q;++i){
            cin>>s>>x>>y;
            if(s=="CHANGE") SinglepointChange(1,x,y);
            else if(s=="QMAX") TreeMax(x,y);
            else TreeSum(x,y);
        }
        return 0;
    }
    inline void add(int x,int y){
        e[++num].v=y;
        e[num].next=head[x];
        head[x]=num;
    }
    int dfs1(int x,int f,int dp){
        fa[x]=f;
        deep[x]=dp;
        siz[x]=1;
        int maxsiz=-1;
        for(register int i=head[x];i;i=e[i].next){
            if(e[i].v==f) continue;
            siz[x]+=dfs1(e[i].v,x,dp+1);
            if(siz[e[i].v]>maxsiz){
                son[x]=e[i].v;
                maxsiz=siz[e[i].v];
            }
        }
        return siz[x];
    }
    inline void dfs2(int x,int topx){
        idn[x]=++cnt;
        top[x]=topx;
        val[cnt]=w[x];
        if(!son[x]) return;
        dfs2(son[x],topx);
        for(register int i=head[x];i;i=e[i].next) if(!idn[e[i].v]) dfs2(e[i].v,e[i].v);
    }
    inline void build(int l,int r,int u){
        t[u].l=l,t[u].r=r;
        if(l==r){
            t[u].w=t[u].maxn=val[l];
            return;
        }
        int m=(l+r)>>1;
        build(l,m,u<<1);
        build(m+1,r,u<<1|1);
        update(u);
    }
    inline void update(int u){
        t[u].w=t[u<<1].w+t[u<<1|1].w;
        t[u].maxn=max(t[u<<1].maxn,t[u<<1|1].maxn);
    }
    int IntervalSum(int u,int l,int r){
        int sum=0;
        if(t[u].l>=l && t[u].r<=r) return t[u].w;
        int m=(t[u].l+t[u].r)>>1;
        if(m>=l) sum+=IntervalSum(u<<1,l,r);
        if(m<r) sum+=IntervalSum(u<<1|1,l,r);
        return sum;
    }
    int IntervalMax(int u,int l,int r){
        int maxn=-1000000000;
        if(t[u].l>=l && t[u].r<=r)    return t[u].maxn;
        int m=(t[u].l+t[u].r)>>1;
        if(m>=l) maxn=max(maxn,IntervalMax(u<<1,l,r));
        if(m<r) maxn=max(maxn,IntervalMax(u<<1|1,l,r));
        return maxn;
    }
    inline void SinglepointChange(int u,int x,int val){
        if(t[u].l==idn[x] && t[u].r==idn[x]){
            t[u].w=t[u].maxn=val;
            return;
        }
        int m=(t[u].l+t[u].r)>>1;
        if(m>=idn[x]) SinglepointChange(u<<1,x,val);
        if(m<idn[x]) SinglepointChange(u<<1|1,x,val);
        update(u);
    }
    inline void TreeSum(int x,int y){
        int ans=0;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            ans+=IntervalSum(1,idn[top[x]],idn[x]);
            x=fa[top[x]]; 
        }
        if(deep[x]>deep[y]) swap(x,y);
        ans+=IntervalSum(1,idn[x],idn[y]);
        printf("%d
    ",ans);
    } 
    inline void TreeMax(int x,int y){
        int maxn=-1000000000;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            maxn=max(maxn,IntervalMax(1,idn[top[x]],idn[x]));
            x=fa[top[x]];
        }
        if(deep[x]>deep[y]) swap(x,y);
        maxn=max(maxn,IntervalMax(1,idn[x],idn[y]));
        printf("%d
    ",maxn);
    }

    树上操作

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M = 500500;
    typedef long long ll;
    struct EDGE{ll v,next;} e[M << 2];
    struct TREE{ll l,r,lz; ll w;} t[M << 2];
    ll n,m,head[M << 2],num,w[M],fa[M],top[M];
    ll idn[M],val[M],son[M],siz[M],deep[M],cnt;
    
    void add(ll,ll);
    ll dfs1(ll,ll,ll);
    void dfs2(ll,ll);
    void build(ll,ll,ll);
    void update(ll);
    void down(ll);
    void SinglepointAdd(ll,ll,ll);
    void IntervalAdd(ll,ll,ll,ll);
    ll IntervalSum(ll,ll,ll);
    void TreeSum(ll x,ll y);
    
    int main(){
        ios::sync_with_stdio(false);
        register int i,j;
        ll q,x,y;
        cin >> n >> m;
        for(i = 1; i <= n; ++i) cin >> w[i];
        for(i = 1; i < n; ++i){
            cin >> x >> y;
            add(x, y);
            add(y, x);
        }
        dfs1(1, 0, 1);
        dfs2(1, 1);
        build(1, n, 1); 
        for(i = 1; i <= m; ++i){
            cin >> q;
            if(q == 1){
                cin >> x >> y;
                SinglepointAdd(1, idn[x], y);
            }
            else if(q == 2){
                cin >> x >> y;
                IntervalAdd(1, idn[x], idn[x]+siz[x]-1, y);
            }
            else{
                cin >> x;
                TreeSum(1, x); 
            }
        }
        return 0;
    }
    
    void add(ll x,ll y){
        e[++num].v = y;
        e[num].next = head[x];
        head[x] = num;
    }
    
    ll dfs1(ll now,ll f,ll dp){
        fa[now] = f;
        deep[now] = dp;
        siz[now] = 1;
        ll maxson = -1;
        for(register int i = head[now]; i; i = e[i].next){
            if(f == e[i].v) continue;
            siz[now] += dfs1(e[i].v, now, dp+1);
            if(maxson < siz[e[i].v]){
                maxson = siz[e[i].v];
                son[now] = e[i].v;
            }
        }
        return siz[now];
    }
    
    void dfs2(ll now,ll topx){
        idn[now] = ++cnt;
        top[now] = topx;
        val[cnt] = w[now];
        if(!son[now]) return;
        dfs2(son[now], topx);
        for(register int i = head[now]; i; i = e[i].next) if(!idn[e[i].v]) dfs2(e[i].v, e[i].v);
    }
    
    void build(ll l,ll r,ll u){
        t[u].l = l,t[u].r = r;
        if(l == r){
            t[u].w = val[l];
            return;
        }
        ll m = (l + r) >> 1;
        build(l, m, u<<1);
        build(m+1, r, u<<1|1);
        update(u);
    }
    
    void update(ll u){
        t[u].w = t[u << 1].w + t[u << 1 | 1].w;
    }
    
    void down(ll u){
        t[u << 1].lz += t[u].lz;
        t[u << 1 | 1].lz += t[u].lz;
        t[u << 1].w += (t[u << 1].r - t[u << 1].l + 1) * t[u].lz;
        t[u << 1 | 1].w += (t[u << 1 | 1].r - t[u << 1 | 1].l + 1) * t[u].lz;
        t[u].lz = 0;
    }
    
    void SinglepointAdd(ll u,ll x,ll add){
        if(t[u].l == x && t[u].l == t[u].r){
            t[u].w += add;
            return;
        }
        if(t[u].lz) down(u);
        ll m = (t[u].l + t[u].r) >> 1;
        if(m >= x) SinglepointAdd(u << 1, x, add);
        if(m < x) SinglepointAdd(u << 1 | 1, x, add);
        update(u);
    }
    
    void IntervalAdd(ll u,ll l,ll r,ll add){
        if(t[u].l >= l && t[u].r <= r){
            t[u].w += (t[u].r - t[u].l + 1) * add;
            t[u].lz += add;
            return;
        }
        if(t[u].lz) down(u);
        ll m = (t[u].l + t[u].r) >> 1;
        if(m >= l) IntervalAdd(u << 1, l, r, add);
        if(m < r) IntervalAdd(u << 1 | 1, l, r, add);
        update(u);
    }
    
    ll IntervalSum(ll u,ll l,ll r){
        ll ans=0;
        if(t[u].l >= l && t[u].r <= r) return t[u].w;
        if(t[u].lz) down(u);
        ll m = (t[u].l + t[u].r) >> 1;
        if(m >= l) ans += IntervalSum(u << 1, l, r);
        if(m < r) ans += IntervalSum(u << 1 | 1, l, r);
        return ans;
    }
    
    void TreeSum(ll x,ll y){
        ll ans = 0;
        while(top[x] != top[y]){
            if(deep[top[x]] < deep[top[y]]) swap(x,y);
            ans += IntervalSum(1, idn[top[x]], idn[x]);
            x = fa[top[x]];
        }
        if(deep[x] > deep[y]) swap(x,y);
        ans += IntervalSum(1,idn[x],idn[y]);
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    容器技术之Dockerfile(一)
    容器技术之Docker常用命令说明
    容器技术之Docker数据卷
    Cypress与TestCafe WebUI端到端测试框架简介
    API测试之Postman使用全指南(原来使用 Postman测试API如此简单)
    【PyMuPDF和pdf2image】Python将PDF转成图片
    2020 | 可替代Selenium的测试框架Top15
    AWS EC2+Docker+JMeter构建分布式负载测试基础架构
    Appium移动端自动化测试--元素操作与触摸动作
    Appium移动端自动化测试--使用IDE编辑并强化脚本
  • 原文地址:https://www.cnblogs.com/Glacier-elk/p/9699714.html
Copyright © 2011-2022 走看看