zoukankan      html  css  js  c++  java
  • [bzoj4372]烁烁的游戏

    来自FallDream的博客,未经允许,请勿转载,谢谢。


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

    n,m<=10^5 wi<=10^4

    让离树上一个点距离小等于d的点的权值加上一个数,这个是可以点分来做的,每次分治都统计一个子树对其它子树的答案的影响。

    这道题就动态点分呗。

    先建出分治结构,然后每个分治的子结构开一个线段树维护不同深度的答案。

    为了去重,每个分治结构的每个子树还要开一个线段树,表示在这个子树内要去掉的答案。

    询问和修改直接从分治结构最底层向上爬,修改或者查询线段树上的值就行了。

    复杂度nlog^2n

    #include<iostream>
    #include<cstdio>
    #define INF 2000000000
    #define MN 100000
    #define MD 18
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    bool b[MN+5];
    int n,m,head[MN+5],cnt=0,mn,rt,tot,dep[MD+5][MN+5],bel[MD+5][MN+5];
    int size[MN+5],mx[MN+5],Fa[MD+5][MN+5],Mxdp[MN+5];
    struct edge{int to,next;}e[MN*2+5]; 
    struct Tree{int l,r,x;}T[20000000];
    inline void ins(int f,int t)
    {
        e[++cnt]=(edge){t,head[f]};head[f]=cnt;
        e[++cnt]=(edge){f,head[t]};head[t]=cnt;
    };
    
    void GetRt(int x,int fa)
    {
        size[x]=1;mx[x]=0;
        for(int i=head[x];i;i=e[i].next)
            if(!b[e[i].to]&&e[i].to!=fa)
            {
                GetRt(e[i].to,x);
                size[x]+=size[e[i].to];
                mx[x]=max(mx[x],size[e[i].to]);
            }    
        int Sz=max(tot-size[x],mx[x]);
        if(Sz<mn) mn=Sz,rt=x;
    }
    
    void Dfs(int x,int fa,int Dep)
    {
        ++tot;
        for(int i=head[x];i;i=e[i].next)
            if(e[i].to!=fa&&!b[e[i].to])
            {
                bel[Dep][e[i].to]=bel[Dep][x];
                dep[Dep][e[i].to]=dep[Dep][x]+1;    
                Dfs(e[i].to,x,Dep);
            }
    }
    
    void Solve(int x,int Dp)
    {
        b[x]=1;bel[Dp][x]=++cnt;Mxdp[x]=Dp;dep[Dp][x]=1;
        for(int i=head[x];i;i=e[i].next)    
            if(!b[e[i].to])
            {
                tot=0;dep[Dp][e[i].to]=2;
                bel[Dp][e[i].to]=++cnt;
                Dfs(e[i].to,x,Dp);
                size[e[i].to]=tot;    
            }
        for(int i=head[x];i;i=e[i].next)
            if(!b[e[i].to])
            {
                tot=size[e[i].to];mn=INF;
                GetRt(e[i].to,x);    
                Fa[Dp+1][rt]=x;
                Solve(rt,Dp+1);
            }
    }
    
    int Query(int x,int v,int lt,int rt)
    {
        if(!x) return 0;
        if(lt==rt) return T[x].x;
        int mid=lt+rt>>1,res;
        if(v<=mid) res=Query(T[x].l,v,lt,mid);
        else       res=Query(T[x].r,v,mid+1,rt);
        return res+T[x].x;
    }
    inline int node(int x){return x?x:++cnt;}
    void Modify(int x,int l,int r,int lt,int rt,int v)
    {
        if(l==lt&&r==rt) {T[x].x+=v;return;}
        int mid=lt+rt>>1;
        if(r<=mid) Modify(T[x].l=node(T[x].l),l,r,lt,mid,v);
        else if(l>mid) Modify(T[x].r=node(T[x].r),l,r,mid+1,rt,v);
        else Modify(T[x].l=node(T[x].l),l,mid,lt,mid,v),
             Modify(T[x].r=node(T[x].r),mid+1,r,mid+1,rt,v);    
    }
    char op[5];
    int main()
    {
        n=read();m=read();
        for(int i=1;i<n;++i) ins(read(),read());
        cnt=0;mn=INF;tot=n;GetRt(1,0);Solve(rt,1);
        for(int ii=1;ii<=m;++ii)
        {
            scanf("%s",op+1);    
            if(op[1]=='Q')
            {
                int x=read(),sum=0;
                for(int j=Mxdp[x],k=x;j;k=Fa[j--][k])
                {
                    sum+=Query(bel[j][k],dep[j][x],1,MN);
                    if(j!=Mxdp[x])
                        sum-=Query(bel[j][x],dep[j][x],1,MN);
                }
                printf("%d
    ",sum);
            }
            else
            {
                int x=read(),d=read(),w=read();
                for(int j=Mxdp[x],k=x;j;k=Fa[j--][k])
                    if(d-dep[j][x]+2>=1)
                    {
                        Modify(bel[j][k],1,d-dep[j][x]+2,1,MN,w);
                        if(Mxdp[x]!=j)
                            Modify(bel[j][x],1,d-dep[j][x]+2,1,MN,w);
                    }    
            }
        }
        return 0;
    }
  • 相关阅读:
    机器学习 —— 多元线性回归
    利用Python实现kNN算法
    Python下的OpenCV学习 02 —— 图像的读取与保存
    Python下的OpenCV学习 01 —— 在Linux下安装OpenCV
    Linux check whether hyperthreading is enabled or not
    Centos7 安装单节点Torque PBS
    CentOS 7中以runfile形式安装CUDA 9.0
    Linux /etc/profile文件详解
    Linux下Makefile学习笔记
    使用 Eigen 3.3.3 进行矩阵运算
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4372.html
Copyright © 2011-2022 走看看