zoukankan      html  css  js  c++  java
  • bzoj 4372: 烁烁的游戏 动态点分治+树链剖分+线段树

    [Submit][Status][Discuss]

    Description

    背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
    题意:
    给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠。
    烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
    烁烁很好奇,在当前时刻,节点u有多少个他的好朋友---皮皮鼠。
    大意:
    给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:
    Q x:询问x的点权。
    M x d w:将树上与节点x距离不超过d的节点的点权均加上w。

    Input

    第一行两个正整数:n,m
    接下来的n-1行,每行三个正整数u,v,代表u,v之间有一条边。
    接下来的m行,每行给出上述两种操作中的一种。

    Output

    对于每个Q操作,输出当前x节点的皮皮鼠数量。

     

    和震波拿到题十分相似,具体做法参考一下震波

    Code:

    #include<bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) 
    #define maxn 6011111 
    #define N 500010  
    #define inf 0x7f7f7f
    using namespace std;
    int hd[N],nx[N],to[N],cnt; 
    int n,m,val[N],vis[N]; 
    void add(int u,int v)
    {
        nx[++cnt]=hd[u],hd[u]=cnt,to[cnt]=v; 
    }
    namespace heavyedge{
        int dep[N],hson[N],fa[N],siz[N],top[N]; 
        void dfs1(int u,int ff)
        {
            dep[u]=dep[ff]+1,fa[u]=ff,siz[u]=1;           
            for(int i=hd[u];i;i=nx[i]) 
                if(to[i]!=ff) 
                {
                    dfs1(to[i],u),siz[u]+=siz[to[i]];
                    if(siz[to[i]]>siz[hson[u]]) hson[u]=to[i]; 
                }
        }
        void dfs2(int u,int tp)    
        {   
            top[u]=tp; 
            if(hson[u]) dfs2(hson[u],tp); 
            for(int i=hd[u];i;i=nx[i])
            {
                if(to[i]==fa[u]||to[i]==hson[u]) continue; 
                dfs2(to[i],to[i]); 
            }
        }
        int LCA(int u,int v)
        {
            while(top[u]!=top[v]) dep[top[u]] < dep[top[v]] ? v = fa[top[v]] : u = fa[top[u]];  
            return dep[u] < dep[v] ? u : v; 
        }
        int main()
        {
            dfs1(1,0), dfs2(1,1); 
            return 0; 
        }
    };   
    int Dis(int u,int v)
    {  
        return heavyedge::dep[u] + heavyedge::dep[v] - (heavyedge::dep[heavyedge::LCA(u,v)] << 1); 
    }   
    int siz[N],f[N],root,sn,Fa[N]; 
    int GetRoot(int u,int ff)
    {
        siz[u] = 1,f[u] = 0; 
        for(int i = hd[u]; i ; i = nx[i]) 
        {
            if(to[i] == ff || vis[to[i]]) continue; 
            GetRoot(to[i],u);     
            siz[u] += siz[to[i]]; 
            f[u] = max(f[u],siz[to[i]]); 
        }
        
        f[u] = max(f[u],sn - siz[u]); 
        if(f[u] < f[root]) root = u; 
    }
    void dfs(int u)
    {
        vis[u] = 1; 
        for(int i = hd[u]; i ; i = nx[i])
        {
            if(vis[to[i]]) continue; 
            root = 0, sn = siz[to[i]], GetRoot(to[i],u);  
            Fa[root] = u, dfs(root); 
        }
    }
    struct Segment_Tree{
        #define ls (t[o].l)
        #define rs (t[o].r) 
        int tot; 
        struct Node
        {
            int l,r,v; 
        }t[maxn<<1]; 
        void update(int &o,int l,int r,int p,int w)
        {
            if(!o) o = ++cnt; 
            t[o].v += w; 
            if(l == r) return; 
            int mid = (l + r) >> 1;
            if(p <= mid) update(t[o].l,l,mid,p,w); 
            else update(t[o].r,mid + 1,r,p,w); 
        }
        
        int query(int o,int l,int r,int L,int R)
        {
            if(!o || l > r) return 0;
            if(l >= L && r <= R) return t[o].v; 
            int mid = (l + r) >> 1,res = 0;   
            if(L <= mid) res += query(t[o].l,l,mid,L,R);
            if(R >= mid + 1) res += query(t[o].r,mid + 1,r, L,R); 
            return res; 
        }
    }T; 
    int ans = 0,rt[N]; 
    #define fax(x) (x + n)          
    void Update(int x,int k,int w)
    {
        T.update(rt[x],0,n,0,w),T.update(rt[x],0,n,k + 1,-w);         
        for(int i = x; Fa[i]; i = Fa[i])         
        {
            int dis = Dis(x, Fa[i]);   
            if(k - dis < 0) continue; 
            T.update(rt[Fa[i]],0,n,0,w),T.update(rt[Fa[i]],0,n,k - dis + 1,-w); 
            T.update(rt[fax(i)],0,n,0,w),T.update(rt[fax(i)],0,n,k - dis + 1,-w); 
        } 
    }
    int Query(int x)
    {
        int res = T.query(rt[x],0,n,0,0); 
        for(int i = x; Fa[i] ; i = Fa[i]) 
        {
            int dis = Dis(x, Fa[i]); 
            res += T.query(rt[Fa[i]],0,n,0,dis); 
            res -= T.query(rt[fax(i)],0,n,0,dis); 
        }      
        return res; 
    }
    char str[20];       
    int main()
    {        
        // setIO("input"); 
        scanf("%d%d",&n,&m);
        for(int i = 1,u,v;i < n; ++i)  scanf("%d%d",&u,&v), add(u,v),add(v,u); 
        heavyedge :: main();       
        f[0] = inf, sn = n,root = 0,GetRoot(1,0), dfs(root);       
        while(m--)
        {
            int x,y,z; 
            scanf("%s",str);       
            if(str[0] == 'M') scanf("%d%d%d",&x,&y,&z),Update(x,y,z);    
            if(str[0] == 'Q') scanf("%d",&x), printf("%d
    ",Query(x)); 
        }      
        return 0; 
    }      
    

      

  • 相关阅读:
    小兔生仔和汽水换瓶的两个算法
    dpi 编程
    作者赠送的《我的第一本c++书》收到啦
    什么是程序员的优良品质
    如何把事情做对?
    学习应有的态度
    魔方数算法
    我的第二本c++教科书
    如何处理人际关系
    电动玩具的开发思路
  • 原文地址:https://www.cnblogs.com/guangheli/p/10921268.html
Copyright © 2011-2022 走看看