zoukankan      html  css  js  c++  java
  • HDU 3966 Aragorn's Story (树链剖分+线段树)

    题意:给你一棵树,然后有三种操作

      I L R K: 把L与R的路径上的所有点权值加上K

      D L R K:把L与R的路径上的所有点权值减去K

      Q X:查询节点编号为X的权值

    思路:树链剖分裸题(我还没有怎么学懂,但基本已经没有什么太大的问题,主要的问题就在于点或者边对于数据结构的映射关系是,主要没有单独手写过树链剖分,所以对这部分 没有什么体会)

    我们知道树链剖分是一种将树剖为链的一种算法,其思想和dfs序差不多,但根据树链剖分的性质,我们的重链是连续的区间,这样对于重链或者重链上的点我们可以方便的用数据结构维护,对于修改操作,是一种类似于LCA的算法,但感觉本质上还是一种LCA,只不过每次向上跳的部分是跳到top,其他的就是两次dfs,分别维护组时候大小以及一些其他的东西,第二遍dfs 找出重链

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn=50008;
    const int maxm=100008;
    
    int n,m,Q;
    int a[maxn],sz[maxn],dep[maxn],fa[maxn],top[maxn],w[maxn],son[maxn];
    int Rank[maxn];
    int sum[maxn<<2],lazy[maxn<<2];
    
    struct line
    {
        int u,v,nxt;
    }eg[maxm];
    int head[maxn],summ,cnt;
    void addedge(int u,int v)
    {
        eg[++summ].u=u;
        eg[summ].v=v;
        eg[summ].nxt=head[u];
        head[u]=summ;
    }
    void add(int u,int v)
    {
        addedge(u,v);addedge(v,u);
    }
    void dfs1(int u)
    {
        sz[u]=1;son[u]=0;
        for(int i=head[u];i;i=eg[i].nxt){
            int v=eg[i].v;
            if(v!=fa[u]){
                fa[v]=u;
                dep[v]=dep[u]+1;
                dfs1(v);
                sz[u]+=sz[v];
                if(sz[v]>sz[son[u]])son[u]=v;
            }
        }
    }
    
    void dfs2(int u,int tp,int x)
    {
        top[u]=tp;w[u]=++cnt;Rank[cnt]=u;
        if(son[u])dfs2(son[u],tp,1);
        for(int i=head[u];i;i=eg[i].nxt){
            int v=eg[i].v;
            if(v==son[u]||v==fa[u])continue;
            dfs2(v,v,2);
        }
    }
    
    void init()
    {
        memset(head,0,sizeof(head));
        summ=1;cnt=0;
        dep[1]=1;fa[1]=0;
    }
    void pushup(int rt)
    {
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void pushdown(int rt,int len)
    {
        if(lazy[rt]){
            lazy[rt<<1]+=lazy[rt];
            lazy[rt<<1|1]+=lazy[rt];
            sum[rt<<1]+=lazy[rt]*(len-len/2);
            sum[rt<<1|1]+=lazy[rt]*(len/2);
            lazy[rt]=0;
        }
    }
    
    void build(int l,int r,int rt)
    {
        lazy[rt]=0;
        if(l==r){
            sum[rt]=a[Rank[l]];
            return ;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        pushup(rt);
    }
    void update(int L,int R,int val,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            sum[rt]+=val*(r-l+1);
            lazy[rt]+=val;
            return ;
        }
        pushdown(rt,r-l+1);
        int mid=(l+r)>>1;
        if(L<=mid)update(L,R,val,l,mid,rt<<1);
        if(mid<R)update(L,R,val,mid+1,r,rt<<1|1);
        pushup(rt);
    }
    
    int query(int x,int l,int r,int rt)
    {
        if(l==r){
            return sum[rt];
        }
        pushdown(rt,r-l+1);
        int mid=(l+r)>>1;
        if(x<=mid)return query(x,l,mid,rt<<1);
        if(mid<x)return query(x,mid+1,r,rt<<1|1);
    }
    void modify(int x,int y,int val)
    {
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            update(w[top[x]],w[x],val,1,n,1);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        update(w[x],w[y],val,1,n,1);
    }
    
    int main()
    {
        while(~scanf("%d%d%d",&n,&m,&Q)){
            init();
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            for(int i=1;i<=m;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v);
            }
            dfs1(1);
            dfs2(1,1,1);
            build(1,cnt,1);
            while (Q--){
                char s[2];
                int x,y,z;
                scanf("%s",s);
                if (s[0]=='I'){
                    scanf("%d %d %d",&x,&y,&z);
                    modify(x,y,z);
                }
                if (s[0]=='D'){
                    scanf("%d %d %d",&x,&y,&z);
                    modify(x,y,-z);
                }
                if (s[0]=='Q'){
                    scanf("%d",&x);
                    printf("%d
    ",query(w[x],1,n,1));
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    hbase 学习笔记一---基本概念
    hdu 4496 (并差集)
    rqnoj-105-核电站问题-dp
    面试之BI-SQL--table转换
    Android:从程序员到架构师之路Ⅲ_高焕堂
    Linux 的进程组、会话、守护进程
    Oracle创建dblink报错:ORA-01017、ORA-02063解决
    JSP 指令
    JSP 生命周期
    JSP 结构
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9740908.html
Copyright © 2011-2022 走看看